@avalabs/fusion-sdk 0.21.0 → 0.23.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/constants.cjs +1 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +9 -1
- package/dist/constants.d.ts +9 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/mod.cjs +1 -1
- package/dist/mod.d.cts +5 -1
- package/dist/mod.d.ts +5 -1
- package/dist/mod.js +1 -1
- package/dist/transfer-manager.cjs +1 -1
- package/dist/transfer-manager.cjs.map +1 -1
- package/dist/transfer-manager.js +1 -1
- package/dist/transfer-manager.js.map +1 -1
- package/dist/transfer-service/_evm-approval.cjs +2 -0
- package/dist/transfer-service/_evm-approval.cjs.map +1 -0
- package/dist/transfer-service/_evm-approval.d.cts +23 -0
- package/dist/transfer-service/_evm-approval.d.ts +23 -0
- package/dist/transfer-service/_evm-approval.js +2 -0
- package/dist/transfer-service/_evm-approval.js.map +1 -0
- package/dist/transfer-service/_utils.cjs +1 -1
- package/dist/transfer-service/_utils.cjs.map +1 -1
- package/dist/transfer-service/_utils.d.ts +1 -0
- package/dist/transfer-service/_utils.js +1 -1
- package/dist/transfer-service/_utils.js.map +1 -1
- package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.cjs +1 -1
- package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.js +1 -1
- package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.js +1 -1
- package/dist/transfer-service/avalanche-cct/_utils/fees.cjs +1 -1
- package/dist/transfer-service/avalanche-cct/_utils/fees.js +1 -1
- package/dist/transfer-service/avalanche-cct/_utils/polling.cjs +1 -1
- package/dist/transfer-service/avalanche-cct/_utils/polling.js +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/markr/_api.cjs +1 -1
- package/dist/transfer-service/markr/_api.cjs.map +1 -1
- package/dist/transfer-service/markr/_api.js +1 -1
- package/dist/transfer-service/markr/_api.js.map +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.cjs.map +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.js +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.js.map +1 -1
- package/dist/transfer-service/markr/_schema.cjs +1 -1
- package/dist/transfer-service/markr/_schema.cjs.map +1 -1
- package/dist/transfer-service/markr/_schema.js +1 -1
- package/dist/transfer-service/markr/_schema.js.map +1 -1
- package/dist/transfer-service/markr/_utils.cjs +1 -1
- package/dist/transfer-service/markr/_utils.cjs.map +1 -1
- package/dist/transfer-service/markr/_utils.js +1 -1
- package/dist/transfer-service/markr/_utils.js.map +1 -1
- package/dist/transfer-service/markr/markr-service.cjs +1 -1
- package/dist/transfer-service/markr/markr-service.cjs.map +1 -1
- package/dist/transfer-service/markr/markr-service.d.cts +26 -0
- package/dist/transfer-service/markr/markr-service.d.ts +26 -0
- package/dist/transfer-service/markr/markr-service.js +1 -1
- package/dist/transfer-service/markr/markr-service.js.map +1 -1
- package/dist/transfer-service/markr/recurring/_api.cjs +2 -0
- package/dist/transfer-service/markr/recurring/_api.cjs.map +1 -0
- package/dist/transfer-service/markr/recurring/_api.js +2 -0
- package/dist/transfer-service/markr/recurring/_api.js.map +1 -0
- package/dist/transfer-service/markr/recurring/_chain-info.cjs +2 -0
- package/dist/transfer-service/markr/recurring/_chain-info.cjs.map +1 -0
- package/dist/transfer-service/markr/recurring/_chain-info.js +2 -0
- package/dist/transfer-service/markr/recurring/_chain-info.js.map +1 -0
- package/dist/transfer-service/markr/recurring/_eligibility.cjs +2 -0
- package/dist/transfer-service/markr/recurring/_eligibility.cjs.map +1 -0
- package/dist/transfer-service/markr/recurring/_eligibility.js +2 -0
- package/dist/transfer-service/markr/recurring/_eligibility.js.map +1 -0
- package/dist/transfer-service/markr/recurring/_frequency.cjs +2 -0
- package/dist/transfer-service/markr/recurring/_frequency.cjs.map +1 -0
- package/dist/transfer-service/markr/recurring/_frequency.d.cts +17 -0
- package/dist/transfer-service/markr/recurring/_frequency.d.ts +17 -0
- package/dist/transfer-service/markr/recurring/_frequency.js +2 -0
- package/dist/transfer-service/markr/recurring/_frequency.js.map +1 -0
- package/dist/transfer-service/markr/recurring/_namespace.cjs +2 -0
- package/dist/transfer-service/markr/recurring/_namespace.cjs.map +1 -0
- package/dist/transfer-service/markr/recurring/_namespace.js +2 -0
- package/dist/transfer-service/markr/recurring/_namespace.js.map +1 -0
- package/dist/transfer-service/markr/recurring/_schema.cjs +2 -0
- package/dist/transfer-service/markr/recurring/_schema.cjs.map +1 -0
- package/dist/transfer-service/markr/recurring/_schema.js +2 -0
- package/dist/transfer-service/markr/recurring/_schema.js.map +1 -0
- package/dist/transfer-service/markr/recurring/index.d.ts +2 -0
- package/dist/transfer-service/markr/recurring/types.cjs +2 -0
- package/dist/transfer-service/markr/recurring/types.cjs.map +1 -0
- package/dist/transfer-service/markr/recurring/types.d.cts +455 -0
- package/dist/transfer-service/markr/recurring/types.d.ts +455 -0
- package/dist/transfer-service/markr/recurring/types.js +2 -0
- package/dist/transfer-service/markr/recurring/types.js.map +1 -0
- package/dist/transfer-service/wrap-unwrap/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/transfer-asset.js +1 -1
- package/dist/types/transfer-manager.d.cts +16 -0
- package/dist/types/transfer-manager.d.ts +16 -0
- package/dist/types/transfer.d.cts +8 -0
- package/dist/types/transfer.d.ts +8 -0
- package/package.json +3 -3
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../errors.cjs`),t=require(`../../../type-guards.cjs`),n=require(`../../_utils.cjs`),r=require(`../../_evm-
|
|
1
|
+
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../errors.cjs`),t=require(`../../../type-guards.cjs`),n=require(`../../_utils.cjs`),r=require(`../../_evm-errors.cjs`),i=require(`../../_evm-gas.cjs`),a=require(`../../_abis.cjs`),o=require(`../_utils/transfer-data.cjs`);let s=require(`viem`);function c({config:c}){let l=c.walletAddresses.ethereum;return async({amountIn:u,assetIn:d,fromAddress:f,sourceChain:p,targetChain:m},h)=>{if(!(0,s.isAddress)(f))throw new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid fromAddress: ${f}`);let{ethToAva:g,source:_}=o.getTransferData({assetIn:d,sourceChainId:p.chainId,targetChainId:m.chainId},c),v=n.getEvmClientForChain({chain:p}),y=0n;if(t.isNativeAsset(d)&&g){y+=await r.estimateGasWithRevert(v,{account:f,to:_.token.address,data:(0,s.encodeFunctionData)({abi:a.WETH_ABI,functionName:`deposit`})},a.WETH_ABI,`Failed to estimate gas for WETH deposit.`);let e=(0,s.encodeFunctionData)({abi:s.erc20Abi,functionName:`transfer`,args:[l,u]});try{y+=await r.estimateGasWithRevert(v,{account:f,to:_.token.address,data:e},s.erc20Abi,`Failed to estimate gas for ERC20 transfer.`)}catch{y+=await r.estimateGasWithRevert(v,{account:f,to:l,data:e,value:u},s.erc20Abi,`Failed to estimate gas for ERC20 transfer (fallback).`)}}else{let e=g?s.erc20Abi:a.WAVAX_ABI;y=await r.estimateGasWithRevert(v,{account:f,to:_.token.address,data:(0,s.encodeFunctionData)({abi:e,functionName:g?`transfer`:`unwrap`,args:g?[l,u]:[u,0n]})},e,`Failed to estimate gas for ${g?`ERC20 transfer`:`WAVAX unwrap`}.`)}let b=await i.estimateEvmFeesPerGas(v,p,h?.overrides?.feeRateTier),x=h?.overrides?.maxFeePerGas??b.maxFeePerGas,S=h?.overrides?.maxPriorityFeePerGas??b.maxPriorityFeePerGas,C=y*x,w=n.applyFeeUnitsBpsMargin(C,h?.feeUnitsMarginBps);return{asset:p.networkToken,totalFee:w,totalFeeWithoutMargin:C,meta:{maxFeePerGas:x,maxPriorityFeePerGas:S}}}}exports.estimateNativeFeeFactory=c;
|
|
2
2
|
//# sourceMappingURL=estimate-native-fee.cjs.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ErrorReason as e,InvalidParamsError as t}from"../../../errors.js";import{isNativeAsset as n}from"../../../type-guards.js";import{applyFeeUnitsBpsMargin as r,getEvmClientForChain as i}from"../../_utils.js";import{
|
|
1
|
+
import{ErrorReason as e,InvalidParamsError as t}from"../../../errors.js";import{isNativeAsset as n}from"../../../type-guards.js";import{applyFeeUnitsBpsMargin as r,getEvmClientForChain as i}from"../../_utils.js";import{estimateGasWithRevert as a}from"../../_evm-errors.js";import{estimateEvmFeesPerGas as o}from"../../_evm-gas.js";import{WAVAX_ABI as s,WETH_ABI as c}from"../../_abis.js";import{getTransferData as l}from"../_utils/transfer-data.js";import{encodeFunctionData as u,erc20Abi as d,isAddress as f}from"viem";function p({config:p}){let m=p.walletAddresses.ethereum;return async({amountIn:h,assetIn:g,fromAddress:_,sourceChain:v,targetChain:y},b)=>{if(!f(_))throw new t(e.INVALID_PARAMS,`Invalid fromAddress: ${_}`);let{ethToAva:x,source:S}=l({assetIn:g,sourceChainId:v.chainId,targetChainId:y.chainId},p),C=i({chain:v}),w=0n;if(n(g)&&x){w+=await a(C,{account:_,to:S.token.address,data:u({abi:c,functionName:`deposit`})},c,`Failed to estimate gas for WETH deposit.`);let e=u({abi:d,functionName:`transfer`,args:[m,h]});try{w+=await a(C,{account:_,to:S.token.address,data:e},d,`Failed to estimate gas for ERC20 transfer.`)}catch{w+=await a(C,{account:_,to:m,data:e,value:h},d,`Failed to estimate gas for ERC20 transfer (fallback).`)}}else{let e=x?d:s;w=await a(C,{account:_,to:S.token.address,data:u({abi:e,functionName:x?`transfer`:`unwrap`,args:x?[m,h]:[h,0n]})},e,`Failed to estimate gas for ${x?`ERC20 transfer`:`WAVAX unwrap`}.`)}let T=await o(C,v,b?.overrides?.feeRateTier),E=b?.overrides?.maxFeePerGas??T.maxFeePerGas,D=b?.overrides?.maxPriorityFeePerGas??T.maxPriorityFeePerGas,O=w*E,k=r(O,b?.feeUnitsMarginBps);return{asset:v.networkToken,totalFee:k,totalFeeWithoutMargin:O,meta:{maxFeePerGas:E,maxPriorityFeePerGas:D}}}}export{p as estimateNativeFeeFactory};
|
|
2
2
|
//# sourceMappingURL=estimate-native-fee.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../../errors.cjs`),t=require(`./_schema.cjs`),n=require(`../fetch-utilities.cjs`);function r(e){if(e)return{Authorization:`Bearer ${e}`}}async function i({apiBaseUrl:i,apiToken:a,fetch:o}){let s=`/info/chains`,c=await n.fetchJson(n.combineUrlPathnames(i,s),{headers:r(a),fetch:o}),l=t.SupportedChainsResponseSchema.safeParse(c);if(!l.success)throw new e.ResponseValidationError(`Invalid response from Markr "${s}" endpoint.`,l.error.issues);return l.data}async function a({apiBaseUrl:i,apiToken:a,fetch:o},s){let c=`/tokens/${s}/list`,l=await n.fetchJson(n.combineUrlPathnames(i,c),{headers:r(a),fetch:o}),u=t.TokenListResponseSchema.safeParse(l);if(!u.success)throw new e.ResponseValidationError(`Invalid response from Markr "${c}" endpoint.`,u.error.issues);return u.data}async function o({apiBaseUrl:i,apiToken:a,fetch:o},s,{onDone:c,onError:l,onQuote:u,signal:d}){let f=`/quote`,p=n.combineUrlPathnames(i,f),m=[];try{for await(let i of n.fetchEventStream(p,{body:JSON.stringify(s),fetch:o,headers:r(a),signal:d})){let n=t.QuoteResponseSchema.safeParse(JSON.parse(i.data));if(!n.success){l(new e.ResponseValidationError(`Invalid quote data received from Markr "${f}" endpoint.`,n.error.issues));continue}`done`in n.data?c():(u(n.data),m.push(n.data))}}catch(e){e instanceof Error?l(e):l(Error(`An unknown error occurred during the quote stream.`,{cause:e})),c()}return m}async function s({apiBaseUrl:i,apiToken:a,fetch:o},s){let c=`/swap`,l=await n.fetchJson(n.combineUrlPathnames(i,c),{body:JSON.stringify(s),fetch:o,headers:r(a),method:`POST`}),u=t.SwapResponseSchema.safeParse(l);if(!u.success)throw new e.ResponseValidationError(`Invalid response from Markr "${c}" endpoint.`,u.error.issues);return u.data}async function c({apiBaseUrl:i,apiToken:a,fetch:o}){let s=`/info/partner`,c=await n.fetchJson(n.combineUrlPathnames(i,s),{headers:r(a),fetch:o}),l=t.PartnerInfoResponseSchema.safeParse(c);if(!l.success)throw new e.ResponseValidationError(`Invalid response from Markr "${s}" endpoint.`,l.error.issues);return l.data}async function l({apiBaseUrl:i,apiToken:a,fetch:o},s,{signal:c}={}){let l=`/cross-chain/status/${s}`,u=await n.fetchJson(n.combineUrlPathnames(i,l),{headers:r(a),fetch:o,retries:10,retryOn(t){let n=(t.init.method??`GET`).toUpperCase();if(![`GET`,`HEAD`,`OPTIONS`,`TRACE`].includes(n))return!1;if(t.error)return!(t.error instanceof e.AbortedError);let r=t.response?.status??0;return r===404||r===408||r===425||r===429||r>=500&&r<=599},signal:c}),d=t.CrossChainStatusResponseSchema.safeParse(u);if(!d.success)throw new e.ResponseValidationError(`Invalid response from Markr "${l}" endpoint.`,d.error.issues,u);return d.data}async function u({apiBaseUrl:i,apiToken:a,fetch:o},{chainId:s,crossChainSwap:c,quoteId:l}){let u=`/spender-address
|
|
1
|
+
const e=require(`../../errors.cjs`),t=require(`./_schema.cjs`),n=require(`../fetch-utilities.cjs`);function r(e){if(e)return{Authorization:`Bearer ${e}`}}async function i({apiBaseUrl:i,apiToken:a,fetch:o}){let s=`/info/chains`,c=await n.fetchJson(n.combineUrlPathnames(i,s),{headers:r(a),fetch:o}),l=t.SupportedChainsResponseSchema.safeParse(c);if(!l.success)throw new e.ResponseValidationError(`Invalid response from Markr "${s}" endpoint.`,l.error.issues);return l.data}async function a({apiBaseUrl:i,apiToken:a,fetch:o},s){let c=`/tokens/${s}/list`,l=await n.fetchJson(n.combineUrlPathnames(i,c),{headers:r(a),fetch:o}),u=t.TokenListResponseSchema.safeParse(l);if(!u.success)throw new e.ResponseValidationError(`Invalid response from Markr "${c}" endpoint.`,u.error.issues);return u.data}async function o({apiBaseUrl:i,apiToken:a,fetch:o},s,{onDone:c,onError:l,onQuote:u,signal:d}){let f=`/quote`,p=n.combineUrlPathnames(i,f),m=[];try{for await(let i of n.fetchEventStream(p,{body:JSON.stringify(s),fetch:o,headers:r(a),signal:d})){let n=t.QuoteResponseSchema.safeParse(JSON.parse(i.data));if(!n.success){l(new e.ResponseValidationError(`Invalid quote data received from Markr "${f}" endpoint.`,n.error.issues));continue}`done`in n.data?c():(u(n.data),m.push(n.data))}}catch(e){e instanceof Error?l(e):l(Error(`An unknown error occurred during the quote stream.`,{cause:e})),c()}return m}async function s({apiBaseUrl:i,apiToken:a,fetch:o},s){let c=`/swap`,l=await n.fetchJson(n.combineUrlPathnames(i,c),{body:JSON.stringify(s),fetch:o,headers:r(a),method:`POST`}),u=t.SwapResponseSchema.safeParse(l);if(!u.success)throw new e.ResponseValidationError(`Invalid response from Markr "${c}" endpoint.`,u.error.issues);return u.data}async function c({apiBaseUrl:i,apiToken:a,fetch:o}){let s=`/info/partner`,c=await n.fetchJson(n.combineUrlPathnames(i,s),{headers:r(a),fetch:o}),l=t.PartnerInfoResponseSchema.safeParse(c);if(!l.success)throw new e.ResponseValidationError(`Invalid response from Markr "${s}" endpoint.`,l.error.issues);return l.data}async function l({apiBaseUrl:i,apiToken:a,fetch:o},s,{signal:c}={}){let l=`/cross-chain/status/${s}`,u=await n.fetchJson(n.combineUrlPathnames(i,l),{headers:r(a),fetch:o,retries:10,retryOn(t){let n=(t.init.method??`GET`).toUpperCase();if(![`GET`,`HEAD`,`OPTIONS`,`TRACE`].includes(n))return!1;if(t.error)return!(t.error instanceof e.AbortedError);let r=t.response?.status??0;return r===404||r===408||r===425||r===429||r>=500&&r<=599},signal:c}),d=t.CrossChainStatusResponseSchema.safeParse(u);if(!d.success)throw new e.ResponseValidationError(`Invalid response from Markr "${l}" endpoint.`,d.error.issues,u);return d.data}async function u({apiBaseUrl:i,apiToken:a,fetch:o},{chainId:s,crossChainSwap:c,quoteId:l}){let u=`/spender-address?${new URLSearchParams({chainId:String(s),cross:c?`true`:`false`,uuid:l}).toString()}`,d=await n.fetchJson(n.combineUrlPathnames(i,u),{headers:r(a),fetch:o}),f=t.SpenderAddressResponseSchema.safeParse(d);if(!f.success)throw new e.ResponseValidationError(`Invalid response from Markr "${u}" endpoint.`,f.error.issues);return f.data}async function d({apiBaseUrl:i,apiToken:a,fetch:o},s,{signal:c}={}){let l=`/authorize`,u=await n.fetchJson(n.combineUrlPathnames(i,l),{body:JSON.stringify(s),fetch:o,headers:r(a),method:`POST`,signal:c}),d=t.MarkrAuthorizeResponseSchema.safeParse(u);if(!d.success)throw new e.ResponseValidationError(`Invalid response from Markr "${l}" endpoint.`,d.error.issues)}exports.getAuthHeaders=r,exports.markrGetCrossChainStatus=l,exports.markrGetInfoChains=i,exports.markrGetPartnerInfo=c,exports.markrGetSpenderAddress=u,exports.markrGetTokenList=a,exports.markrPostAuthorize=d,exports.markrStreamQuote=o,exports.markrSwap=s;
|
|
2
2
|
//# sourceMappingURL=_api.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_api.cjs","names":["fetchJson","combineUrlPathnames","SupportedChainsResponseSchema","ResponseValidationError","TokenListResponseSchema","fetchEventStream","QuoteResponseSchema","SwapResponseSchema","PartnerInfoResponseSchema","AbortedError","CrossChainStatusResponseSchema","SpenderAddressResponseSchema","MarkrAuthorizeResponseSchema"],"sources":["../../../src/transfer-service/markr/_api.ts"],"sourcesContent":["import type { Address as SolanaAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport { AbortedError, ResponseValidationError } from '../../errors';\nimport { combineUrlPathnames, fetchEventStream, fetchJson } from '../fetch-utilities';\nimport {\n CrossChainStatusResponseSchema,\n MarkrAuthorizeResponseSchema,\n PartnerInfoResponseSchema,\n QuoteResponseSchema,\n SpenderAddressResponseSchema,\n SupportedChainsResponseSchema,\n SwapResponseSchema,\n TokenListResponseSchema,\n type CrossChainStatusResponse,\n type PartnerInfoResponse,\n type QuoteResponseData,\n type SpenderAddressResponse,\n type SupportedChainsResponse,\n type SwapResponse,\n type TokenListResponse,\n} from './_schema';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Fetch } from '../../types/utility-types';\n\nexport interface ApiOptions {\n apiBaseUrl: URL;\n apiToken?: string;\n fetch?: Fetch;\n}\n\nfunction getAuthHeaders(apiToken?: string): Record<string, string> | undefined {\n if (!apiToken) {\n return undefined;\n }\n\n return { Authorization: `Bearer ${apiToken}` };\n}\n\nexport async function markrGetInfoChains({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<SupportedChainsResponse> {\n const endpoint = '/info/chains';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SupportedChainsResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetTokenList(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n chainId: number,\n): Promise<TokenListResponse> {\n const endpoint = `/tokens/${chainId}/list`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = TokenListResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport interface MarkrStreamQuoteParams {\n amount: string;\n /**\n * Pin the quote to a single upstream aggregator (e.g. `\"relay\"`). When\n * omitted, Markr races every eligible aggregator. Used to obtain\n * native-fee-free routes that only a specific aggregator supports.\n */\n aggregator?: string;\n appId: string;\n chainId: number | Caip2ChainId;\n destinationChainId?: number | Caip2ChainId;\n slippage?: number;\n tokenIn: string;\n tokenInDecimals: number;\n tokenOut: string;\n tokenOutDecimals: number;\n /**\n * Required ONLY for cross-chain swaps involving EVM.\n *\n * EVM -> EVM (different chains)\n * EVM -> Solana\n * Solana -> EVM\n */\n userEvmAddress?: EvmAddress;\n /**\n * Required ONLY for cross-chain swaps involving Solana.\n *\n * Solana -> EVM\n * EVM -> Solana\n * Solana -> Solana\n */\n userSolanaAddress?: SolanaAddress;\n}\n\nexport interface MarkrStreamQuoteOptions {\n onDone: () => void;\n onError: (error: Error) => void;\n onQuote: (data: QuoteResponseData) => void;\n signal?: AbortSignal;\n}\n\nexport async function markrStreamQuote(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrStreamQuoteParams,\n { onDone, onError, onQuote, signal }: MarkrStreamQuoteOptions,\n): Promise<ReadonlyArray<QuoteResponseData>> {\n const endpoint = '/quote';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const quotes: QuoteResponseData[] = [];\n\n try {\n for await (const event of fetchEventStream(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n signal,\n })) {\n const parsedData = QuoteResponseSchema.safeParse(JSON.parse(event.data));\n\n if (!parsedData.success) {\n onError(\n new ResponseValidationError(\n `Invalid quote data received from Markr \"${endpoint}\" endpoint.`,\n parsedData.error.issues,\n ),\n );\n continue;\n }\n\n if (!('done' in parsedData.data)) {\n onQuote(parsedData.data);\n quotes.push(parsedData.data);\n } else {\n onDone();\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n onError(error);\n } else {\n onError(new Error('An unknown error occurred during the quote stream.', { cause: error }));\n }\n\n onDone();\n }\n\n return quotes;\n}\n\nexport interface MarkrGetSwapParams {\n appId: string;\n /** Input amount in token's smallest unit */\n amountIn: string;\n /** Return raw transaction data alongside wrapped data */\n debug?: boolean;\n /** Minimum expected output amount */\n minAmountOut: string;\n /** Input token contract address */\n tokenIn: string;\n /** Output token contract address */\n tokenOut: string;\n /** Solana wallet public key (required for Solana swaps) */\n userPublicKey?: string;\n /** Quote UUID from previous quote request */\n uuid: string;\n}\n\nexport async function markrSwap(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrGetSwapParams,\n): Promise<SwapResponse> {\n const endpoint = '/swap';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n });\n\n const parsed = SwapResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetPartnerInfo({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<PartnerInfoResponse> {\n const endpoint = '/info/partner';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = PartnerInfoResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetCrossChainStatus(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n sourceTxHash: string,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<CrossChainStatusResponse> {\n const endpoint = `/cross-chain/status/${sourceTxHash}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n headers: getAuthHeaders(apiToken),\n fetch: customFetch,\n retries: 10,\n retryOn(ctx) {\n const method = (ctx.init.method ?? 'GET').toUpperCase();\n\n if (!['GET', 'HEAD', 'OPTIONS', 'TRACE'].includes(method)) {\n return false;\n }\n\n if (ctx.error) {\n if (ctx.error instanceof AbortedError) {\n return false;\n }\n\n return true;\n }\n\n const status = ctx.response?.status ?? 0;\n\n // Retry on 404 requests since the endpoint may not return a result immediately after the source transaction is executed.\n if (status === 404 || status === 408 || status === 425 || status === 429 || (status >= 500 && status <= 599)) {\n return true;\n }\n\n return false;\n },\n signal,\n });\n\n const parsed = CrossChainStatusResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(\n `Invalid response from Markr \"${endpoint}\" endpoint.`,\n parsed.error.issues,\n rawJson,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Returns the spender address (wrapped contract) that needs to be approved\n * for token swaps on the specified chain.\n *\n * Not applicable for Solana.\n */\nexport async function markrGetSpenderAddress(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n {\n chainId,\n crossChainSwap,\n quoteId,\n }: {\n chainId: number;\n crossChainSwap?: boolean;\n quoteId: string;\n },\n): Promise<SpenderAddressResponse> {\n const endpoint = `/spender-address?chainId=${chainId}&cross=${crossChainSwap ? 'true' : 'false'}&uuid=${quoteId}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SpenderAddressResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Hyperliquid 2-phase withdrawal: nonce-mapping authorize\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy (`protocolVersion: 1`) authorize body — Markr rebuilds the upstream\n * Relay request from a fixed schema. Kept for back-compat; new integrations\n * should use {@link MarkrPostAuthorizeParamsV2}.\n *\n * **Caveat:** when Relay adds a required field (as it did with `depositor` in\n * v2), the rebuilt body silently omits it and the order is orphaned upstream.\n */\nexport interface MarkrPostAuthorizeParamsV1 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over the `RelayNonceMapping` typed data (`0x{r}{s}{v}`, 65 bytes hex). */\n readonly signature: `0x${string}`;\n /** EVM address of the signer. */\n readonly wallet: EvmAddress;\n /** Always `1337` (Hyperliquid). */\n readonly walletChainId: 1337;\n /** EIP-712 domain.chainId used in the signature — the wallet's active chain. */\n readonly signatureChainId: number;\n /**\n * Shared nonce — JSON number, matching Relay's upstream `/authorize` contract\n * and HL `/exchange`. HL nonces are millisecond timestamps, well under\n * `Number.MAX_SAFE_INTEGER`. Sending it as a string makes Relay reject the\n * payload (strict type validation), so we coerce here at the wire boundary.\n */\n readonly nonce: number;\n /** Relay request id (`0x{64hex}`). */\n readonly id: `0x${string}`;\n}\n\n/**\n * Pass-through (`protocolVersion: 2`) authorize body. The SDK forwards Relay's\n * `authorize.body` envelope from the `/swap` response **verbatim**. Markr only\n * normalizes `nonce` to a JSON number and defaults `referrer`; every other\n * field is untouched, so additive Relay schema changes don't break SDKs.\n */\nexport interface MarkrPostAuthorizeParamsV2 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over `swap.sign.value` using `swap.sign.domain` / `swap.sign.types`. */\n readonly signature: `0x${string}`;\n /** Relay's `/authorize` POST body, taken from `swap.authorize.body`. Forwarded verbatim. */\n readonly body: Record<string, unknown>;\n}\n\nexport type MarkrPostAuthorizeParams = MarkrPostAuthorizeParamsV1 | MarkrPostAuthorizeParamsV2;\n\n/**\n * Submit the user's signed nonce-mapping to Markr's `/authorize` endpoint.\n *\n * Markr proxies the request to Relay's upstream `/authorize`. Returns on any\n * 2xx; throws `HttpError` otherwise.\n */\nexport async function markrPostAuthorize(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrPostAuthorizeParams,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<void> {\n const endpoint = '/authorize';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n // `fetchJson` throws `HttpError` on non-2xx; the schema additionally rejects\n // upstream error envelopes that come back with a 200 (Relay sometimes does\n // this when authorize is rejected after HTTP success).\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n signal,\n });\n\n const parsed = MarkrAuthorizeResponseSchema.safeParse(rawJson);\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"_api.cjs","names":["fetchJson","combineUrlPathnames","SupportedChainsResponseSchema","ResponseValidationError","TokenListResponseSchema","fetchEventStream","QuoteResponseSchema","SwapResponseSchema","PartnerInfoResponseSchema","AbortedError","CrossChainStatusResponseSchema","SpenderAddressResponseSchema","MarkrAuthorizeResponseSchema"],"sources":["../../../src/transfer-service/markr/_api.ts"],"sourcesContent":["import type { Address as SolanaAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport { AbortedError, ResponseValidationError } from '../../errors';\nimport { combineUrlPathnames, fetchEventStream, fetchJson } from '../fetch-utilities';\nimport {\n CrossChainStatusResponseSchema,\n MarkrAuthorizeResponseSchema,\n PartnerInfoResponseSchema,\n QuoteResponseSchema,\n SpenderAddressResponseSchema,\n SupportedChainsResponseSchema,\n SwapResponseSchema,\n TokenListResponseSchema,\n type CrossChainStatusResponse,\n type PartnerInfoResponse,\n type QuoteResponseData,\n type SpenderAddressResponse,\n type SupportedChainsResponse,\n type SwapResponse,\n type TokenListResponse,\n} from './_schema';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Fetch } from '../../types/utility-types';\n\nexport interface ApiOptions {\n apiBaseUrl: URL;\n apiToken?: string;\n fetch?: Fetch;\n}\n\nexport function getAuthHeaders(apiToken?: string): Record<string, string> | undefined {\n if (!apiToken) {\n return undefined;\n }\n\n return { Authorization: `Bearer ${apiToken}` };\n}\n\nexport async function markrGetInfoChains({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<SupportedChainsResponse> {\n const endpoint = '/info/chains';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SupportedChainsResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetTokenList(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n chainId: number,\n): Promise<TokenListResponse> {\n const endpoint = `/tokens/${chainId}/list`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = TokenListResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport interface MarkrStreamQuoteParams {\n amount: string;\n /**\n * Pin the quote to a single upstream aggregator (e.g. `\"relay\"`). When\n * omitted, Markr races every eligible aggregator. Used to obtain\n * native-fee-free routes that only a specific aggregator supports.\n */\n aggregator?: string;\n appId: string;\n chainId: number | Caip2ChainId;\n destinationChainId?: number | Caip2ChainId;\n slippage?: number;\n tokenIn: string;\n tokenInDecimals: number;\n tokenOut: string;\n tokenOutDecimals: number;\n /**\n * Required ONLY for cross-chain swaps involving EVM.\n *\n * EVM -> EVM (different chains)\n * EVM -> Solana\n * Solana -> EVM\n */\n userEvmAddress?: EvmAddress;\n /**\n * Required ONLY for cross-chain swaps involving Solana.\n *\n * Solana -> EVM\n * EVM -> Solana\n * Solana -> Solana\n */\n userSolanaAddress?: SolanaAddress;\n}\n\nexport interface MarkrStreamQuoteOptions {\n onDone: () => void;\n onError: (error: Error) => void;\n onQuote: (data: QuoteResponseData) => void;\n signal?: AbortSignal;\n}\n\nexport async function markrStreamQuote(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrStreamQuoteParams,\n { onDone, onError, onQuote, signal }: MarkrStreamQuoteOptions,\n): Promise<ReadonlyArray<QuoteResponseData>> {\n const endpoint = '/quote';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const quotes: QuoteResponseData[] = [];\n\n try {\n for await (const event of fetchEventStream(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n signal,\n })) {\n const parsedData = QuoteResponseSchema.safeParse(JSON.parse(event.data));\n\n if (!parsedData.success) {\n onError(\n new ResponseValidationError(\n `Invalid quote data received from Markr \"${endpoint}\" endpoint.`,\n parsedData.error.issues,\n ),\n );\n continue;\n }\n\n if (!('done' in parsedData.data)) {\n onQuote(parsedData.data);\n quotes.push(parsedData.data);\n } else {\n onDone();\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n onError(error);\n } else {\n onError(new Error('An unknown error occurred during the quote stream.', { cause: error }));\n }\n\n onDone();\n }\n\n return quotes;\n}\n\nexport interface MarkrGetSwapParams {\n appId: string;\n /** Input amount in token's smallest unit */\n amountIn: string;\n /** Return raw transaction data alongside wrapped data */\n debug?: boolean;\n /** Minimum expected output amount */\n minAmountOut: string;\n /** Input token contract address */\n tokenIn: string;\n /** Output token contract address */\n tokenOut: string;\n /** Solana wallet public key (required for Solana swaps) */\n userPublicKey?: string;\n /** Quote UUID from previous quote request */\n uuid: string;\n}\n\nexport async function markrSwap(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrGetSwapParams,\n): Promise<SwapResponse> {\n const endpoint = '/swap';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n });\n\n const parsed = SwapResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetPartnerInfo({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<PartnerInfoResponse> {\n const endpoint = '/info/partner';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = PartnerInfoResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetCrossChainStatus(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n sourceTxHash: string,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<CrossChainStatusResponse> {\n const endpoint = `/cross-chain/status/${sourceTxHash}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n headers: getAuthHeaders(apiToken),\n fetch: customFetch,\n retries: 10,\n retryOn(ctx) {\n const method = (ctx.init.method ?? 'GET').toUpperCase();\n\n if (!['GET', 'HEAD', 'OPTIONS', 'TRACE'].includes(method)) {\n return false;\n }\n\n if (ctx.error) {\n if (ctx.error instanceof AbortedError) {\n return false;\n }\n\n return true;\n }\n\n const status = ctx.response?.status ?? 0;\n\n // Retry on 404 requests since the endpoint may not return a result immediately after the source transaction is executed.\n if (status === 404 || status === 408 || status === 425 || status === 429 || (status >= 500 && status <= 599)) {\n return true;\n }\n\n return false;\n },\n signal,\n });\n\n const parsed = CrossChainStatusResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(\n `Invalid response from Markr \"${endpoint}\" endpoint.`,\n parsed.error.issues,\n rawJson,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Returns the spender address (wrapped contract) that needs to be approved\n * for token swaps on the specified chain.\n *\n * Not applicable for Solana.\n */\nexport async function markrGetSpenderAddress(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n {\n chainId,\n crossChainSwap,\n quoteId,\n }: {\n chainId: number;\n crossChainSwap?: boolean;\n quoteId: string;\n },\n): Promise<SpenderAddressResponse> {\n // Use `URLSearchParams` rather than template-string concatenation so the\n // `quoteId` is URL-encoded — defense-in-depth against a caller passing a\n // value with a stray `&`/`=` that would otherwise inject extra query params.\n const searchParams = new URLSearchParams({\n chainId: String(chainId),\n cross: crossChainSwap ? 'true' : 'false',\n uuid: quoteId,\n });\n const endpoint = `/spender-address?${searchParams.toString()}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SpenderAddressResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Hyperliquid 2-phase withdrawal: nonce-mapping authorize\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy (`protocolVersion: 1`) authorize body — Markr rebuilds the upstream\n * Relay request from a fixed schema. Kept for back-compat; new integrations\n * should use {@link MarkrPostAuthorizeParamsV2}.\n *\n * **Caveat:** when Relay adds a required field (as it did with `depositor` in\n * v2), the rebuilt body silently omits it and the order is orphaned upstream.\n */\nexport interface MarkrPostAuthorizeParamsV1 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over the `RelayNonceMapping` typed data (`0x{r}{s}{v}`, 65 bytes hex). */\n readonly signature: `0x${string}`;\n /** EVM address of the signer. */\n readonly wallet: EvmAddress;\n /** Always `1337` (Hyperliquid). */\n readonly walletChainId: 1337;\n /** EIP-712 domain.chainId used in the signature — the wallet's active chain. */\n readonly signatureChainId: number;\n /**\n * Shared nonce — JSON number, matching Relay's upstream `/authorize` contract\n * and HL `/exchange`. HL nonces are millisecond timestamps, well under\n * `Number.MAX_SAFE_INTEGER`. Sending it as a string makes Relay reject the\n * payload (strict type validation), so we coerce here at the wire boundary.\n */\n readonly nonce: number;\n /** Relay request id (`0x{64hex}`). */\n readonly id: `0x${string}`;\n}\n\n/**\n * Pass-through (`protocolVersion: 2`) authorize body. The SDK forwards Relay's\n * `authorize.body` envelope from the `/swap` response **verbatim**. Markr only\n * normalizes `nonce` to a JSON number and defaults `referrer`; every other\n * field is untouched, so additive Relay schema changes don't break SDKs.\n */\nexport interface MarkrPostAuthorizeParamsV2 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over `swap.sign.value` using `swap.sign.domain` / `swap.sign.types`. */\n readonly signature: `0x${string}`;\n /** Relay's `/authorize` POST body, taken from `swap.authorize.body`. Forwarded verbatim. */\n readonly body: Record<string, unknown>;\n}\n\nexport type MarkrPostAuthorizeParams = MarkrPostAuthorizeParamsV1 | MarkrPostAuthorizeParamsV2;\n\n/**\n * Submit the user's signed nonce-mapping to Markr's `/authorize` endpoint.\n *\n * Markr proxies the request to Relay's upstream `/authorize`. Returns on any\n * 2xx; throws `HttpError` otherwise.\n */\nexport async function markrPostAuthorize(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrPostAuthorizeParams,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<void> {\n const endpoint = '/authorize';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n // `fetchJson` throws `HttpError` on non-2xx; the schema additionally rejects\n // upstream error envelopes that come back with a 200 (Relay sometimes does\n // this when authorize is rejected after HTTP success).\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n signal,\n });\n\n const parsed = MarkrAuthorizeResponseSchema.safeParse(rawJson);\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{AbortedError as e,ResponseValidationError as t}from"../../errors.js";import{CrossChainStatusResponseSchema as n,MarkrAuthorizeResponseSchema as r,PartnerInfoResponseSchema as i,QuoteResponseSchema as a,SpenderAddressResponseSchema as o,SupportedChainsResponseSchema as s,SwapResponseSchema as c,TokenListResponseSchema as l}from"./_schema.js";import{combineUrlPathnames as u,fetchEventStream as d,fetchJson as f}from"../fetch-utilities.js";function p(e){if(e)return{Authorization:`Bearer ${e}`}}async function m({apiBaseUrl:e,apiToken:n,fetch:r}){let i=`/info/chains`,a=await f(u(e,i),{headers:p(n),fetch:r}),o=s.safeParse(a);if(!o.success)throw new t(`Invalid response from Markr "${i}" endpoint.`,o.error.issues);return o.data}async function h({apiBaseUrl:e,apiToken:n,fetch:r},i){let a=`/tokens/${i}/list`,o=await f(u(e,a),{headers:p(n),fetch:r}),s=l.safeParse(o);if(!s.success)throw new t(`Invalid response from Markr "${a}" endpoint.`,s.error.issues);return s.data}async function g({apiBaseUrl:e,apiToken:n,fetch:r},i,{onDone:o,onError:s,onQuote:c,signal:l}){let f=`/quote`,m=u(e,f),h=[];try{for await(let e of d(m,{body:JSON.stringify(i),fetch:r,headers:p(n),signal:l})){let n=a.safeParse(JSON.parse(e.data));if(!n.success){s(new t(`Invalid quote data received from Markr "${f}" endpoint.`,n.error.issues));continue}`done`in n.data?o():(c(n.data),h.push(n.data))}}catch(e){e instanceof Error?s(e):s(Error(`An unknown error occurred during the quote stream.`,{cause:e})),o()}return h}async function _({apiBaseUrl:e,apiToken:n,fetch:r},i){let a=`/swap`,o=await f(u(e,a),{body:JSON.stringify(i),fetch:r,headers:p(n),method:`POST`}),s=c.safeParse(o);if(!s.success)throw new t(`Invalid response from Markr "${a}" endpoint.`,s.error.issues);return s.data}async function v({apiBaseUrl:e,apiToken:n,fetch:r}){let a=`/info/partner`,o=await f(u(e,a),{headers:p(n),fetch:r}),s=i.safeParse(o);if(!s.success)throw new t(`Invalid response from Markr "${a}" endpoint.`,s.error.issues);return s.data}async function y({apiBaseUrl:r,apiToken:i,fetch:a},o,{signal:s}={}){let c=`/cross-chain/status/${o}`,l=await f(u(r,c),{headers:p(i),fetch:a,retries:10,retryOn(t){let n=(t.init.method??`GET`).toUpperCase();if(![`GET`,`HEAD`,`OPTIONS`,`TRACE`].includes(n))return!1;if(t.error)return!(t.error instanceof e);let r=t.response?.status??0;return r===404||r===408||r===425||r===429||r>=500&&r<=599},signal:s}),d=n.safeParse(l);if(!d.success)throw new t(`Invalid response from Markr "${c}" endpoint.`,d.error.issues,l);return d.data}async function b({apiBaseUrl:e,apiToken:n,fetch:r},{chainId:i,crossChainSwap:a,quoteId:s}){let c=`/spender-address
|
|
1
|
+
import{AbortedError as e,ResponseValidationError as t}from"../../errors.js";import{CrossChainStatusResponseSchema as n,MarkrAuthorizeResponseSchema as r,PartnerInfoResponseSchema as i,QuoteResponseSchema as a,SpenderAddressResponseSchema as o,SupportedChainsResponseSchema as s,SwapResponseSchema as c,TokenListResponseSchema as l}from"./_schema.js";import{combineUrlPathnames as u,fetchEventStream as d,fetchJson as f}from"../fetch-utilities.js";function p(e){if(e)return{Authorization:`Bearer ${e}`}}async function m({apiBaseUrl:e,apiToken:n,fetch:r}){let i=`/info/chains`,a=await f(u(e,i),{headers:p(n),fetch:r}),o=s.safeParse(a);if(!o.success)throw new t(`Invalid response from Markr "${i}" endpoint.`,o.error.issues);return o.data}async function h({apiBaseUrl:e,apiToken:n,fetch:r},i){let a=`/tokens/${i}/list`,o=await f(u(e,a),{headers:p(n),fetch:r}),s=l.safeParse(o);if(!s.success)throw new t(`Invalid response from Markr "${a}" endpoint.`,s.error.issues);return s.data}async function g({apiBaseUrl:e,apiToken:n,fetch:r},i,{onDone:o,onError:s,onQuote:c,signal:l}){let f=`/quote`,m=u(e,f),h=[];try{for await(let e of d(m,{body:JSON.stringify(i),fetch:r,headers:p(n),signal:l})){let n=a.safeParse(JSON.parse(e.data));if(!n.success){s(new t(`Invalid quote data received from Markr "${f}" endpoint.`,n.error.issues));continue}`done`in n.data?o():(c(n.data),h.push(n.data))}}catch(e){e instanceof Error?s(e):s(Error(`An unknown error occurred during the quote stream.`,{cause:e})),o()}return h}async function _({apiBaseUrl:e,apiToken:n,fetch:r},i){let a=`/swap`,o=await f(u(e,a),{body:JSON.stringify(i),fetch:r,headers:p(n),method:`POST`}),s=c.safeParse(o);if(!s.success)throw new t(`Invalid response from Markr "${a}" endpoint.`,s.error.issues);return s.data}async function v({apiBaseUrl:e,apiToken:n,fetch:r}){let a=`/info/partner`,o=await f(u(e,a),{headers:p(n),fetch:r}),s=i.safeParse(o);if(!s.success)throw new t(`Invalid response from Markr "${a}" endpoint.`,s.error.issues);return s.data}async function y({apiBaseUrl:r,apiToken:i,fetch:a},o,{signal:s}={}){let c=`/cross-chain/status/${o}`,l=await f(u(r,c),{headers:p(i),fetch:a,retries:10,retryOn(t){let n=(t.init.method??`GET`).toUpperCase();if(![`GET`,`HEAD`,`OPTIONS`,`TRACE`].includes(n))return!1;if(t.error)return!(t.error instanceof e);let r=t.response?.status??0;return r===404||r===408||r===425||r===429||r>=500&&r<=599},signal:s}),d=n.safeParse(l);if(!d.success)throw new t(`Invalid response from Markr "${c}" endpoint.`,d.error.issues,l);return d.data}async function b({apiBaseUrl:e,apiToken:n,fetch:r},{chainId:i,crossChainSwap:a,quoteId:s}){let c=`/spender-address?${new URLSearchParams({chainId:String(i),cross:a?`true`:`false`,uuid:s}).toString()}`,l=await f(u(e,c),{headers:p(n),fetch:r}),d=o.safeParse(l);if(!d.success)throw new t(`Invalid response from Markr "${c}" endpoint.`,d.error.issues);return d.data}async function x({apiBaseUrl:e,apiToken:n,fetch:i},a,{signal:o}={}){let s=`/authorize`,c=await f(u(e,s),{body:JSON.stringify(a),fetch:i,headers:p(n),method:`POST`,signal:o}),l=r.safeParse(c);if(!l.success)throw new t(`Invalid response from Markr "${s}" endpoint.`,l.error.issues)}export{p as getAuthHeaders,y as markrGetCrossChainStatus,m as markrGetInfoChains,v as markrGetPartnerInfo,b as markrGetSpenderAddress,h as markrGetTokenList,x as markrPostAuthorize,g as markrStreamQuote,_ as markrSwap};
|
|
2
2
|
//# sourceMappingURL=_api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_api.js","names":[],"sources":["../../../src/transfer-service/markr/_api.ts"],"sourcesContent":["import type { Address as SolanaAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport { AbortedError, ResponseValidationError } from '../../errors';\nimport { combineUrlPathnames, fetchEventStream, fetchJson } from '../fetch-utilities';\nimport {\n CrossChainStatusResponseSchema,\n MarkrAuthorizeResponseSchema,\n PartnerInfoResponseSchema,\n QuoteResponseSchema,\n SpenderAddressResponseSchema,\n SupportedChainsResponseSchema,\n SwapResponseSchema,\n TokenListResponseSchema,\n type CrossChainStatusResponse,\n type PartnerInfoResponse,\n type QuoteResponseData,\n type SpenderAddressResponse,\n type SupportedChainsResponse,\n type SwapResponse,\n type TokenListResponse,\n} from './_schema';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Fetch } from '../../types/utility-types';\n\nexport interface ApiOptions {\n apiBaseUrl: URL;\n apiToken?: string;\n fetch?: Fetch;\n}\n\nfunction getAuthHeaders(apiToken?: string): Record<string, string> | undefined {\n if (!apiToken) {\n return undefined;\n }\n\n return { Authorization: `Bearer ${apiToken}` };\n}\n\nexport async function markrGetInfoChains({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<SupportedChainsResponse> {\n const endpoint = '/info/chains';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SupportedChainsResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetTokenList(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n chainId: number,\n): Promise<TokenListResponse> {\n const endpoint = `/tokens/${chainId}/list`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = TokenListResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport interface MarkrStreamQuoteParams {\n amount: string;\n /**\n * Pin the quote to a single upstream aggregator (e.g. `\"relay\"`). When\n * omitted, Markr races every eligible aggregator. Used to obtain\n * native-fee-free routes that only a specific aggregator supports.\n */\n aggregator?: string;\n appId: string;\n chainId: number | Caip2ChainId;\n destinationChainId?: number | Caip2ChainId;\n slippage?: number;\n tokenIn: string;\n tokenInDecimals: number;\n tokenOut: string;\n tokenOutDecimals: number;\n /**\n * Required ONLY for cross-chain swaps involving EVM.\n *\n * EVM -> EVM (different chains)\n * EVM -> Solana\n * Solana -> EVM\n */\n userEvmAddress?: EvmAddress;\n /**\n * Required ONLY for cross-chain swaps involving Solana.\n *\n * Solana -> EVM\n * EVM -> Solana\n * Solana -> Solana\n */\n userSolanaAddress?: SolanaAddress;\n}\n\nexport interface MarkrStreamQuoteOptions {\n onDone: () => void;\n onError: (error: Error) => void;\n onQuote: (data: QuoteResponseData) => void;\n signal?: AbortSignal;\n}\n\nexport async function markrStreamQuote(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrStreamQuoteParams,\n { onDone, onError, onQuote, signal }: MarkrStreamQuoteOptions,\n): Promise<ReadonlyArray<QuoteResponseData>> {\n const endpoint = '/quote';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const quotes: QuoteResponseData[] = [];\n\n try {\n for await (const event of fetchEventStream(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n signal,\n })) {\n const parsedData = QuoteResponseSchema.safeParse(JSON.parse(event.data));\n\n if (!parsedData.success) {\n onError(\n new ResponseValidationError(\n `Invalid quote data received from Markr \"${endpoint}\" endpoint.`,\n parsedData.error.issues,\n ),\n );\n continue;\n }\n\n if (!('done' in parsedData.data)) {\n onQuote(parsedData.data);\n quotes.push(parsedData.data);\n } else {\n onDone();\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n onError(error);\n } else {\n onError(new Error('An unknown error occurred during the quote stream.', { cause: error }));\n }\n\n onDone();\n }\n\n return quotes;\n}\n\nexport interface MarkrGetSwapParams {\n appId: string;\n /** Input amount in token's smallest unit */\n amountIn: string;\n /** Return raw transaction data alongside wrapped data */\n debug?: boolean;\n /** Minimum expected output amount */\n minAmountOut: string;\n /** Input token contract address */\n tokenIn: string;\n /** Output token contract address */\n tokenOut: string;\n /** Solana wallet public key (required for Solana swaps) */\n userPublicKey?: string;\n /** Quote UUID from previous quote request */\n uuid: string;\n}\n\nexport async function markrSwap(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrGetSwapParams,\n): Promise<SwapResponse> {\n const endpoint = '/swap';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n });\n\n const parsed = SwapResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetPartnerInfo({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<PartnerInfoResponse> {\n const endpoint = '/info/partner';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = PartnerInfoResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetCrossChainStatus(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n sourceTxHash: string,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<CrossChainStatusResponse> {\n const endpoint = `/cross-chain/status/${sourceTxHash}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n headers: getAuthHeaders(apiToken),\n fetch: customFetch,\n retries: 10,\n retryOn(ctx) {\n const method = (ctx.init.method ?? 'GET').toUpperCase();\n\n if (!['GET', 'HEAD', 'OPTIONS', 'TRACE'].includes(method)) {\n return false;\n }\n\n if (ctx.error) {\n if (ctx.error instanceof AbortedError) {\n return false;\n }\n\n return true;\n }\n\n const status = ctx.response?.status ?? 0;\n\n // Retry on 404 requests since the endpoint may not return a result immediately after the source transaction is executed.\n if (status === 404 || status === 408 || status === 425 || status === 429 || (status >= 500 && status <= 599)) {\n return true;\n }\n\n return false;\n },\n signal,\n });\n\n const parsed = CrossChainStatusResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(\n `Invalid response from Markr \"${endpoint}\" endpoint.`,\n parsed.error.issues,\n rawJson,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Returns the spender address (wrapped contract) that needs to be approved\n * for token swaps on the specified chain.\n *\n * Not applicable for Solana.\n */\nexport async function markrGetSpenderAddress(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n {\n chainId,\n crossChainSwap,\n quoteId,\n }: {\n chainId: number;\n crossChainSwap?: boolean;\n quoteId: string;\n },\n): Promise<SpenderAddressResponse> {\n const endpoint = `/spender-address?chainId=${chainId}&cross=${crossChainSwap ? 'true' : 'false'}&uuid=${quoteId}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SpenderAddressResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Hyperliquid 2-phase withdrawal: nonce-mapping authorize\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy (`protocolVersion: 1`) authorize body — Markr rebuilds the upstream\n * Relay request from a fixed schema. Kept for back-compat; new integrations\n * should use {@link MarkrPostAuthorizeParamsV2}.\n *\n * **Caveat:** when Relay adds a required field (as it did with `depositor` in\n * v2), the rebuilt body silently omits it and the order is orphaned upstream.\n */\nexport interface MarkrPostAuthorizeParamsV1 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over the `RelayNonceMapping` typed data (`0x{r}{s}{v}`, 65 bytes hex). */\n readonly signature: `0x${string}`;\n /** EVM address of the signer. */\n readonly wallet: EvmAddress;\n /** Always `1337` (Hyperliquid). */\n readonly walletChainId: 1337;\n /** EIP-712 domain.chainId used in the signature — the wallet's active chain. */\n readonly signatureChainId: number;\n /**\n * Shared nonce — JSON number, matching Relay's upstream `/authorize` contract\n * and HL `/exchange`. HL nonces are millisecond timestamps, well under\n * `Number.MAX_SAFE_INTEGER`. Sending it as a string makes Relay reject the\n * payload (strict type validation), so we coerce here at the wire boundary.\n */\n readonly nonce: number;\n /** Relay request id (`0x{64hex}`). */\n readonly id: `0x${string}`;\n}\n\n/**\n * Pass-through (`protocolVersion: 2`) authorize body. The SDK forwards Relay's\n * `authorize.body` envelope from the `/swap` response **verbatim**. Markr only\n * normalizes `nonce` to a JSON number and defaults `referrer`; every other\n * field is untouched, so additive Relay schema changes don't break SDKs.\n */\nexport interface MarkrPostAuthorizeParamsV2 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over `swap.sign.value` using `swap.sign.domain` / `swap.sign.types`. */\n readonly signature: `0x${string}`;\n /** Relay's `/authorize` POST body, taken from `swap.authorize.body`. Forwarded verbatim. */\n readonly body: Record<string, unknown>;\n}\n\nexport type MarkrPostAuthorizeParams = MarkrPostAuthorizeParamsV1 | MarkrPostAuthorizeParamsV2;\n\n/**\n * Submit the user's signed nonce-mapping to Markr's `/authorize` endpoint.\n *\n * Markr proxies the request to Relay's upstream `/authorize`. Returns on any\n * 2xx; throws `HttpError` otherwise.\n */\nexport async function markrPostAuthorize(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrPostAuthorizeParams,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<void> {\n const endpoint = '/authorize';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n // `fetchJson` throws `HttpError` on non-2xx; the schema additionally rejects\n // upstream error envelopes that come back with a 200 (Relay sometimes does\n // this when authorize is rejected after HTTP success).\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n signal,\n });\n\n const parsed = MarkrAuthorizeResponseSchema.safeParse(rawJson);\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"_api.js","names":[],"sources":["../../../src/transfer-service/markr/_api.ts"],"sourcesContent":["import type { Address as SolanaAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport { AbortedError, ResponseValidationError } from '../../errors';\nimport { combineUrlPathnames, fetchEventStream, fetchJson } from '../fetch-utilities';\nimport {\n CrossChainStatusResponseSchema,\n MarkrAuthorizeResponseSchema,\n PartnerInfoResponseSchema,\n QuoteResponseSchema,\n SpenderAddressResponseSchema,\n SupportedChainsResponseSchema,\n SwapResponseSchema,\n TokenListResponseSchema,\n type CrossChainStatusResponse,\n type PartnerInfoResponse,\n type QuoteResponseData,\n type SpenderAddressResponse,\n type SupportedChainsResponse,\n type SwapResponse,\n type TokenListResponse,\n} from './_schema';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Fetch } from '../../types/utility-types';\n\nexport interface ApiOptions {\n apiBaseUrl: URL;\n apiToken?: string;\n fetch?: Fetch;\n}\n\nexport function getAuthHeaders(apiToken?: string): Record<string, string> | undefined {\n if (!apiToken) {\n return undefined;\n }\n\n return { Authorization: `Bearer ${apiToken}` };\n}\n\nexport async function markrGetInfoChains({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<SupportedChainsResponse> {\n const endpoint = '/info/chains';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SupportedChainsResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetTokenList(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n chainId: number,\n): Promise<TokenListResponse> {\n const endpoint = `/tokens/${chainId}/list`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = TokenListResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport interface MarkrStreamQuoteParams {\n amount: string;\n /**\n * Pin the quote to a single upstream aggregator (e.g. `\"relay\"`). When\n * omitted, Markr races every eligible aggregator. Used to obtain\n * native-fee-free routes that only a specific aggregator supports.\n */\n aggregator?: string;\n appId: string;\n chainId: number | Caip2ChainId;\n destinationChainId?: number | Caip2ChainId;\n slippage?: number;\n tokenIn: string;\n tokenInDecimals: number;\n tokenOut: string;\n tokenOutDecimals: number;\n /**\n * Required ONLY for cross-chain swaps involving EVM.\n *\n * EVM -> EVM (different chains)\n * EVM -> Solana\n * Solana -> EVM\n */\n userEvmAddress?: EvmAddress;\n /**\n * Required ONLY for cross-chain swaps involving Solana.\n *\n * Solana -> EVM\n * EVM -> Solana\n * Solana -> Solana\n */\n userSolanaAddress?: SolanaAddress;\n}\n\nexport interface MarkrStreamQuoteOptions {\n onDone: () => void;\n onError: (error: Error) => void;\n onQuote: (data: QuoteResponseData) => void;\n signal?: AbortSignal;\n}\n\nexport async function markrStreamQuote(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrStreamQuoteParams,\n { onDone, onError, onQuote, signal }: MarkrStreamQuoteOptions,\n): Promise<ReadonlyArray<QuoteResponseData>> {\n const endpoint = '/quote';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const quotes: QuoteResponseData[] = [];\n\n try {\n for await (const event of fetchEventStream(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n signal,\n })) {\n const parsedData = QuoteResponseSchema.safeParse(JSON.parse(event.data));\n\n if (!parsedData.success) {\n onError(\n new ResponseValidationError(\n `Invalid quote data received from Markr \"${endpoint}\" endpoint.`,\n parsedData.error.issues,\n ),\n );\n continue;\n }\n\n if (!('done' in parsedData.data)) {\n onQuote(parsedData.data);\n quotes.push(parsedData.data);\n } else {\n onDone();\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n onError(error);\n } else {\n onError(new Error('An unknown error occurred during the quote stream.', { cause: error }));\n }\n\n onDone();\n }\n\n return quotes;\n}\n\nexport interface MarkrGetSwapParams {\n appId: string;\n /** Input amount in token's smallest unit */\n amountIn: string;\n /** Return raw transaction data alongside wrapped data */\n debug?: boolean;\n /** Minimum expected output amount */\n minAmountOut: string;\n /** Input token contract address */\n tokenIn: string;\n /** Output token contract address */\n tokenOut: string;\n /** Solana wallet public key (required for Solana swaps) */\n userPublicKey?: string;\n /** Quote UUID from previous quote request */\n uuid: string;\n}\n\nexport async function markrSwap(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrGetSwapParams,\n): Promise<SwapResponse> {\n const endpoint = '/swap';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n });\n\n const parsed = SwapResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetPartnerInfo({\n apiBaseUrl,\n apiToken,\n fetch: customFetch,\n}: ApiOptions): Promise<PartnerInfoResponse> {\n const endpoint = '/info/partner';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = PartnerInfoResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\nexport async function markrGetCrossChainStatus(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n sourceTxHash: string,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<CrossChainStatusResponse> {\n const endpoint = `/cross-chain/status/${sourceTxHash}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, {\n headers: getAuthHeaders(apiToken),\n fetch: customFetch,\n retries: 10,\n retryOn(ctx) {\n const method = (ctx.init.method ?? 'GET').toUpperCase();\n\n if (!['GET', 'HEAD', 'OPTIONS', 'TRACE'].includes(method)) {\n return false;\n }\n\n if (ctx.error) {\n if (ctx.error instanceof AbortedError) {\n return false;\n }\n\n return true;\n }\n\n const status = ctx.response?.status ?? 0;\n\n // Retry on 404 requests since the endpoint may not return a result immediately after the source transaction is executed.\n if (status === 404 || status === 408 || status === 425 || status === 429 || (status >= 500 && status <= 599)) {\n return true;\n }\n\n return false;\n },\n signal,\n });\n\n const parsed = CrossChainStatusResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(\n `Invalid response from Markr \"${endpoint}\" endpoint.`,\n parsed.error.issues,\n rawJson,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Returns the spender address (wrapped contract) that needs to be approved\n * for token swaps on the specified chain.\n *\n * Not applicable for Solana.\n */\nexport async function markrGetSpenderAddress(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n {\n chainId,\n crossChainSwap,\n quoteId,\n }: {\n chainId: number;\n crossChainSwap?: boolean;\n quoteId: string;\n },\n): Promise<SpenderAddressResponse> {\n // Use `URLSearchParams` rather than template-string concatenation so the\n // `quoteId` is URL-encoded — defense-in-depth against a caller passing a\n // value with a stray `&`/`=` that would otherwise inject extra query params.\n const searchParams = new URLSearchParams({\n chainId: String(chainId),\n cross: crossChainSwap ? 'true' : 'false',\n uuid: quoteId,\n });\n const endpoint = `/spender-address?${searchParams.toString()}`;\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n const rawJson = await fetchJson(url, { headers: getAuthHeaders(apiToken), fetch: customFetch });\n\n const parsed = SpenderAddressResponseSchema.safeParse(rawJson);\n\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Hyperliquid 2-phase withdrawal: nonce-mapping authorize\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy (`protocolVersion: 1`) authorize body — Markr rebuilds the upstream\n * Relay request from a fixed schema. Kept for back-compat; new integrations\n * should use {@link MarkrPostAuthorizeParamsV2}.\n *\n * **Caveat:** when Relay adds a required field (as it did with `depositor` in\n * v2), the rebuilt body silently omits it and the order is orphaned upstream.\n */\nexport interface MarkrPostAuthorizeParamsV1 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over the `RelayNonceMapping` typed data (`0x{r}{s}{v}`, 65 bytes hex). */\n readonly signature: `0x${string}`;\n /** EVM address of the signer. */\n readonly wallet: EvmAddress;\n /** Always `1337` (Hyperliquid). */\n readonly walletChainId: 1337;\n /** EIP-712 domain.chainId used in the signature — the wallet's active chain. */\n readonly signatureChainId: number;\n /**\n * Shared nonce — JSON number, matching Relay's upstream `/authorize` contract\n * and HL `/exchange`. HL nonces are millisecond timestamps, well under\n * `Number.MAX_SAFE_INTEGER`. Sending it as a string makes Relay reject the\n * payload (strict type validation), so we coerce here at the wire boundary.\n */\n readonly nonce: number;\n /** Relay request id (`0x{64hex}`). */\n readonly id: `0x${string}`;\n}\n\n/**\n * Pass-through (`protocolVersion: 2`) authorize body. The SDK forwards Relay's\n * `authorize.body` envelope from the `/swap` response **verbatim**. Markr only\n * normalizes `nonce` to a JSON number and defaults `referrer`; every other\n * field is untouched, so additive Relay schema changes don't break SDKs.\n */\nexport interface MarkrPostAuthorizeParamsV2 {\n /** Quote uuid — lets Markr correlate the authorize call with the cached Relay step. */\n readonly uuid: string;\n /** User's EIP-712 signature over `swap.sign.value` using `swap.sign.domain` / `swap.sign.types`. */\n readonly signature: `0x${string}`;\n /** Relay's `/authorize` POST body, taken from `swap.authorize.body`. Forwarded verbatim. */\n readonly body: Record<string, unknown>;\n}\n\nexport type MarkrPostAuthorizeParams = MarkrPostAuthorizeParamsV1 | MarkrPostAuthorizeParamsV2;\n\n/**\n * Submit the user's signed nonce-mapping to Markr's `/authorize` endpoint.\n *\n * Markr proxies the request to Relay's upstream `/authorize`. Returns on any\n * 2xx; throws `HttpError` otherwise.\n */\nexport async function markrPostAuthorize(\n { apiBaseUrl, apiToken, fetch: customFetch }: ApiOptions,\n params: MarkrPostAuthorizeParams,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<void> {\n const endpoint = '/authorize';\n const url = combineUrlPathnames(apiBaseUrl, endpoint);\n\n // `fetchJson` throws `HttpError` on non-2xx; the schema additionally rejects\n // upstream error envelopes that come back with a 200 (Relay sometimes does\n // this when authorize is rejected after HTTP success).\n const rawJson = await fetchJson(url, {\n body: JSON.stringify(params),\n fetch: customFetch,\n headers: getAuthHeaders(apiToken),\n method: 'POST',\n signal,\n });\n\n const parsed = MarkrAuthorizeResponseSchema.safeParse(rawJson);\n if (!parsed.success) {\n throw new ResponseValidationError(`Invalid response from Markr \"${endpoint}\" endpoint.`, parsed.error.issues);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../errors.cjs`),t=require(`../../../utils/caip.cjs`),n=require(`../../_utils.cjs`),r=require(
|
|
1
|
+
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../errors.cjs`),t=require(`../../../utils/caip.cjs`),n=require(`../../_utils.cjs`),r=require(`../../_evm-errors.cjs`),i=require(`../../../_utils/chain.cjs`),a=require(`../../_evm-gas.cjs`),o=require(`../_api.cjs`),s=require(`../_utils.cjs`),c=require(`../_type-guards.cjs`),l=require(`../../../utils/solana.cjs`);let u=require(`viem`),d=require(`@solana/kit`);function f(t){return async(n,r)=>{if(i.isEvmNamespace(n.sourceChain.chainId))return await p(n,r,t);if(i.isSolanaNamespace(n.sourceChain.chainId))return await m(n,r,t);throw new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Unsupported source chain namespace for estimateNativeFee: ${n.sourceChain.chainId}`)}}async function p(i,l,{apiOptions:d,appId:f}){if(!(0,u.isAddress)(i.fromAddress))throw new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid fromAddress: ${i.fromAddress}`);let p=n.getEvmClientForChain({chain:i.sourceChain}),m=s.assetToAddressString(i.assetIn,i.sourceChain.chainId);if(!(0,u.isAddress)(m))throw new e.SdkError(e.ErrorReason.INVALID_PARAMS,e.ErrorCode.INVALID_PARAMS,{details:`assetIn address is not a valid EVM address. Can not call estimateGas.`});let g=s.isTokenAddressNative(m),_=i.sourceChain.chainId.toLowerCase()!==i.targetChain.chainId.toLowerCase(),v=i.amountIn+s.getAdditiveSourceAssetFeeAmount(i),y=0n;if(!g){let n,{address:a}=await o.markrGetSpenderAddress(d,{chainId:t.caip2ToEip155ChainId(i.sourceChain.chainId),crossChainSwap:_,quoteId:i.id});try{n=await p.readContract({address:m,abi:u.erc20Abi,functionName:`allowance`,args:[i.fromAddress,a]})}catch(t){throw new e.SdkError(`Error during allowance check`,e.ErrorCode.VIEM_ERROR,{cause:t,details:`Failed to read ERC20 allowance for Markr spender.`})}n<v&&(y=await r.estimateGasWithRevert(p,{account:i.fromAddress,to:m,data:(0,u.encodeFunctionData)({abi:u.erc20Abi,functionName:`approve`,args:[a,v]})},u.erc20Abi,`Failed to estimate gas for ERC20 approval transaction.`))}let b=y>0n,x=s.calculateMarkrMinimumAmountOut({amountOut:i.amountOut,assetOut:i.assetOut,slippageBps:i.slippageBps}),S=await o.markrSwap(d,{amountIn:i.amountIn.toString(),appId:f,minAmountOut:x.toString(),tokenIn:m,tokenOut:s.assetToAddressString(i.assetOut,i.targetChain.chainId),uuid:i.id});if(!c.isEvmSwapResponse(S)){let t=c.isSolanaSwapResponse(S)?S.chainType:c.isHyperliquidWithdrawSwapResponse(S)?S.type:`unknown`;throw new e.SdkError(e.ErrorReason.CHAIN_NOT_SUPPORTED,e.ErrorCode.INVALID_PARAMS,{details:`Received non-EVM swap response from Markr. Expected EVM transaction data for gas estimation, but got response variant "${t}".`})}let C=0n;C=b?i.gasEstimate||700000n:await h({crossChain:_,fromAddress:i.fromAddress,sourceClient:p,swap:S});let w=await a.estimateEvmFeesPerGas(p,i.sourceChain,l?.overrides?.feeRateTier),T=l?.overrides?.maxFeePerGas??w.maxFeePerGas,E=l?.overrides?.maxPriorityFeePerGas??w.maxPriorityFeePerGas,D=(C+y)*T;return{asset:i.sourceChain.networkToken,totalFee:n.applyFeeUnitsBpsMargin(D,l?.feeUnitsMarginBps),totalFeeWithoutMargin:D,meta:{approvalFee:b?y*T:void 0,maxFeePerGas:T,maxPriorityFeePerGas:E}}}async function m(t,r,{apiOptions:i,appId:a}){let u=s.assetToAddressString(t.assetIn,t.sourceChain.chainId);if(!(0,d.isAddress)(u))throw new e.SdkError(e.ErrorReason.INVALID_PARAMS,e.ErrorCode.INVALID_PARAMS,{details:`assetIn address is not a valid Solana address. Can not call estimateGas.`});let f=s.getAdditiveSourceNativeAssetFeeAmount(t),p=t.amountIn+f,m=s.calculateMarkrMinimumAmountOut({amountOut:t.amountOut,assetOut:t.assetOut,slippageBps:t.slippageBps}),h=await o.markrSwap(i,{amountIn:t.amountIn.toString(),appId:a,minAmountOut:m.toString(),tokenIn:u,tokenOut:s.assetToAddressString(t.assetOut,t.targetChain.chainId),userPublicKey:t.fromAddress,uuid:t.id});if(!c.isSolanaSwapResponse(h))throw new e.SdkError(e.ErrorReason.CHAIN_NOT_SUPPORTED,e.ErrorCode.INVALID_PARAMS,{details:`Received non-Solana swap response from Markr. Expected Solana transaction data for fee estimation.`});let{baseFeeLamports:g,priorityFeeLamports:_,...v}=await l.estimateSolanaFee(n.getSolanaRpcForChain({chain:t.sourceChain}),h.swapTransaction),y=v.feePayerBalanceDiffLamports-p;return{asset:t.sourceChain.networkToken,totalFee:n.applyFeeUnitsBpsMargin(y,r?.feeUnitsMarginBps),totalFeeWithoutMargin:y,meta:{...v,baseFee:g,priorityFee:_}}}async function h({crossChain:e,feeUnitsMarginBps:t,fromAddress:i,sourceClient:a,swap:o}){let c=await s.getMarkrSwapWrapperAbi(e);return n.applyFeeUnitsBpsMargin(await r.estimateGasWithRevert(a,{account:i,to:o.to,data:o.data,value:o.value},c,`Failed to estimate gas for Markr swap transaction.`),t)}exports._estimateGasFromSwapResponse=h,exports.estimateNativeFeeFactory=f;
|
|
2
2
|
//# sourceMappingURL=estimate-native-fee.cjs.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ErrorCode as e,ErrorReason as t,InvalidParamsError as n,SdkError as r}from"../../../errors.js";import{caip2ToEip155ChainId as i}from"../../../utils/caip.js";import{applyFeeUnitsBpsMargin as a,getEvmClientForChain as o,getSolanaRpcForChain as s}from"../../_utils.js";import{
|
|
1
|
+
import{ErrorCode as e,ErrorReason as t,InvalidParamsError as n,SdkError as r}from"../../../errors.js";import{caip2ToEip155ChainId as i}from"../../../utils/caip.js";import{applyFeeUnitsBpsMargin as a,getEvmClientForChain as o,getSolanaRpcForChain as s}from"../../_utils.js";import{estimateGasWithRevert as c}from"../../_evm-errors.js";import{isEvmNamespace as l,isSolanaNamespace as u}from"../../../_utils/chain.js";import{estimateEvmFeesPerGas as d}from"../../_evm-gas.js";import{markrGetSpenderAddress as f,markrSwap as p}from"../_api.js";import{assetToAddressString as m,calculateMarkrMinimumAmountOut as h,getAdditiveSourceAssetFeeAmount as g,getAdditiveSourceNativeAssetFeeAmount as _,getMarkrSwapWrapperAbi as v,isTokenAddressNative as y}from"../_utils.js";import{isEvmSwapResponse as b,isHyperliquidWithdrawSwapResponse as x,isSolanaSwapResponse as S}from"../_type-guards.js";import{estimateSolanaFee as C}from"../../../utils/solana.js";import{encodeFunctionData as w,erc20Abi as T,isAddress as E}from"viem";import{isAddress as D}from"@solana/kit";function O(e){return async(r,i)=>{if(l(r.sourceChain.chainId))return await k(r,i,e);if(u(r.sourceChain.chainId))return await A(r,i,e);throw new n(t.INVALID_PARAMS,`Unsupported source chain namespace for estimateNativeFee: ${r.sourceChain.chainId}`)}}async function k(s,l,{apiOptions:u,appId:_}){if(!E(s.fromAddress))throw new n(t.INVALID_PARAMS,`Invalid fromAddress: ${s.fromAddress}`);let v=o({chain:s.sourceChain}),C=m(s.assetIn,s.sourceChain.chainId);if(!E(C))throw new r(t.INVALID_PARAMS,e.INVALID_PARAMS,{details:`assetIn address is not a valid EVM address. Can not call estimateGas.`});let D=y(C),O=s.sourceChain.chainId.toLowerCase()!==s.targetChain.chainId.toLowerCase(),k=s.amountIn+g(s),A=0n;if(!D){let t,{address:n}=await f(u,{chainId:i(s.sourceChain.chainId),crossChainSwap:O,quoteId:s.id});try{t=await v.readContract({address:C,abi:T,functionName:`allowance`,args:[s.fromAddress,n]})}catch(t){throw new r(`Error during allowance check`,e.VIEM_ERROR,{cause:t,details:`Failed to read ERC20 allowance for Markr spender.`})}t<k&&(A=await c(v,{account:s.fromAddress,to:C,data:w({abi:T,functionName:`approve`,args:[n,k]})},T,`Failed to estimate gas for ERC20 approval transaction.`))}let M=A>0n,N=h({amountOut:s.amountOut,assetOut:s.assetOut,slippageBps:s.slippageBps}),P=await p(u,{amountIn:s.amountIn.toString(),appId:_,minAmountOut:N.toString(),tokenIn:C,tokenOut:m(s.assetOut,s.targetChain.chainId),uuid:s.id});if(!b(P)){let n=S(P)?P.chainType:x(P)?P.type:`unknown`;throw new r(t.CHAIN_NOT_SUPPORTED,e.INVALID_PARAMS,{details:`Received non-EVM swap response from Markr. Expected EVM transaction data for gas estimation, but got response variant "${n}".`})}let F=0n;F=M?s.gasEstimate||700000n:await j({crossChain:O,fromAddress:s.fromAddress,sourceClient:v,swap:P});let I=await d(v,s.sourceChain,l?.overrides?.feeRateTier),L=l?.overrides?.maxFeePerGas??I.maxFeePerGas,R=l?.overrides?.maxPriorityFeePerGas??I.maxPriorityFeePerGas,z=(F+A)*L;return{asset:s.sourceChain.networkToken,totalFee:a(z,l?.feeUnitsMarginBps),totalFeeWithoutMargin:z,meta:{approvalFee:M?A*L:void 0,maxFeePerGas:L,maxPriorityFeePerGas:R}}}async function A(n,i,{apiOptions:o,appId:c}){let l=m(n.assetIn,n.sourceChain.chainId);if(!D(l))throw new r(t.INVALID_PARAMS,e.INVALID_PARAMS,{details:`assetIn address is not a valid Solana address. Can not call estimateGas.`});let u=_(n),d=n.amountIn+u,f=h({amountOut:n.amountOut,assetOut:n.assetOut,slippageBps:n.slippageBps}),g=await p(o,{amountIn:n.amountIn.toString(),appId:c,minAmountOut:f.toString(),tokenIn:l,tokenOut:m(n.assetOut,n.targetChain.chainId),userPublicKey:n.fromAddress,uuid:n.id});if(!S(g))throw new r(t.CHAIN_NOT_SUPPORTED,e.INVALID_PARAMS,{details:`Received non-Solana swap response from Markr. Expected Solana transaction data for fee estimation.`});let{baseFeeLamports:v,priorityFeeLamports:y,...b}=await C(s({chain:n.sourceChain}),g.swapTransaction),x=b.feePayerBalanceDiffLamports-d;return{asset:n.sourceChain.networkToken,totalFee:a(x,i?.feeUnitsMarginBps),totalFeeWithoutMargin:x,meta:{...b,baseFee:v,priorityFee:y}}}async function j({crossChain:e,feeUnitsMarginBps:t,fromAddress:n,sourceClient:r,swap:i}){let o=await v(e);return a(await c(r,{account:n,to:i.to,data:i.data,value:i.value},o,`Failed to estimate gas for Markr swap transaction.`),t)}export{j as _estimateGasFromSwapResponse,O as estimateNativeFeeFactory};
|
|
2
2
|
//# sourceMappingURL=estimate-native-fee.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../../../utils/caip.cjs`),r=require(`../../_utils.cjs`),i=require(
|
|
1
|
+
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../../../utils/caip.cjs`),r=require(`../../_utils.cjs`),i=require(`../../_evm-approval.cjs`),a=require(`../../../_utils/chain.cjs`),o=require(`../_api.cjs`),s=require(`../../../utils/sol-address.cjs`),c=require(`../_utils.cjs`),l=require(`../_type-guards.cjs`),u=require(`../../../utils/solana.cjs`),d=require(`./estimate-native-fee.cjs`),f=require(`./transfer-asset-hyperliquid-withdraw.cjs`);let p=require(`viem`);function m({apiOptions:n,appId:r,environment:i,evmSigner:o,solanaSigner:s}){return async({quote:c,gasSettings:l,fallbackToDefaultOnBatchFailure:u,onStepChange:d})=>{if(c.serviceType!==e.ServiceType.MARKR)throw new t.SdkError(t.ErrorReason.INCORRECT_PROVIDER_PROVIDED,t.ErrorCode.INVALID_PARAMS);let f=Math.floor(Date.now()/1e3);if(c.expiresAt<=f)throw new t.SdkError(t.ErrorReason.QUOTE_EXPIRED,t.ErrorCode.INVALID_PARAMS);let p=c.sourceChain.chainId;if(p===e.HyperliquidChainIds.MAINNET)return h({apiOptions:n,appId:r,environment:i,evmSigner:o,quote:c,onStepChange:d});if(a.isSolanaNamespace(p))return _({apiOptions:n,appId:r,environment:i,solanaSigner:s,quote:c,onStepChange:d});if(a.isEvmNamespace(p))return g({apiOptions:n,appId:r,environment:i,evmSigner:o,quote:c,gasSettings:l,fallbackToDefaultOnBatchFailure:u,onStepChange:d});throw new t.SdkError(t.ErrorReason.CHAIN_NOT_SUPPORTED,t.ErrorCode.INVALID_PARAMS,{details:`Unsupported source chain namespace: ${p}`})}}async function h({apiOptions:e,appId:n,environment:r,evmSigner:i,quote:a,onStepChange:s}){let u=c.calculateMarkrMinimumAmountOut({amountOut:a.amountOut,assetOut:a.assetOut,slippageBps:a.slippageBps}),d=c.assetToAddressString(a.assetIn,a.sourceChain.chainId),p=c.assetToAddressString(a.assetOut,a.targetChain.chainId),m=await o.markrSwap(e,{amountIn:a.amountIn.toString(),appId:n,minAmountOut:u.toString(),tokenIn:d,tokenOut:p,uuid:a.id});if(!l.isHyperliquidWithdrawSwapResponse(m))throw new t.SdkError(t.ErrorReason.CHAIN_NOT_SUPPORTED,t.ErrorCode.INVALID_PARAMS,{details:"Expected `hyperliquid-withdraw` swap response from Markr for Hyperliquid source chain, but received a different variant."});return f._executeHyperliquidWithdraw({apiOptions:e,environment:r,evmSigner:i,quote:a,swap:m,onStepChange:s})}async function g({apiOptions:a,appId:s,environment:u,evmSigner:f,quote:m,gasSettings:h,fallbackToDefaultOnBatchFailure:g,onStepChange:_}){let y=m.fromAddress;if(!(0,p.isAddress)(y))throw new t.SdkError(t.ErrorReason.INVALID_PARAMS,t.ErrorCode.INVALID_PARAMS,{details:`fromAddress is not a valid EVM address.`});let b=c.calculateMarkrMinimumAmountOut({amountOut:m.amountOut,assetOut:m.assetOut,slippageBps:m.slippageBps}),x=r.getEvmClientForChain({chain:m.sourceChain}),S=c.assetToAddressString(m.assetIn,m.sourceChain.chainId),C=c.assetToAddressString(m.assetOut,m.targetChain.chainId);if(!(0,p.isAddress)(S))throw new t.SdkError(t.ErrorReason.INVALID_PARAMS,t.ErrorCode.INVALID_PARAMS,{details:`assetIn address is not a valid EVM address.`});let w=S,T=c.isTokenAddressNative(w),E=m.sourceChain.chainId.toLowerCase()!==m.targetChain.chainId.toLowerCase(),D=m.amountIn+c.getAdditiveSourceAssetFeeAmount(m),{address:O}=await o.markrGetSpenderAddress(a,{chainId:n.caip2ToEip155ChainId(m.sourceChain.chainId),crossChainSwap:E,quoteId:m.id});if(!T&&!O)throw new t.SdkError(t.ErrorReason.CHAIN_NOT_SUPPORTED,t.ErrorCode.INVALID_PARAMS,{details:`Missing Markr spender address for source chain ${m.sourceChain.chainId}.`});let k=!T&&O?await i.buildErc20ApprovalRequest({chainIdHex:n.caip2ToEip155HexChainId(m.sourceChain.chainId),client:x,gasSettings:h,owner:y,requiredAllowance:D,spender:O,token:w}):void 0,A=k!==void 0,j=v({approvalRequest:k,requiresApprovalSignature:A,signBatch:f.signBatch,sourceChainId:m.sourceChain.chainId,targetChainId:m.targetChain.chainId}),M=await o.markrSwap(a,{amountIn:m.amountIn.toString(),appId:s,minAmountOut:b.toString(),tokenIn:S,tokenOut:C,uuid:m.id});if(!l.isEvmSwapResponse(M))throw new t.SdkError(t.ErrorReason.CHAIN_NOT_SUPPORTED,t.ErrorCode.INVALID_PARAMS,{details:`Received non-EVM swap response from Markr, but only EVM swaps are supported for this source chain.`});let N=(t,n=Date.now())=>{let r=m.sourceChain.chainId===m.targetChain.chainId;return{amountIn:m.amountIn,amountOut:m.amountOut,environment:u,fees:m.fees,fromAddress:m.fromAddress,id:m.id,partnerFeeBps:m.partnerFeeBps,sourceAsset:m.assetIn,sourceChain:m.sourceChain,status:`source-pending`,targetAsset:m.assetOut,targetChain:m.targetChain,toAddress:m.toAddress,type:e.ServiceType.MARKR,source:{confirmationCount:0,requiredConfirmationCount:r?1:2,startedAtMs:n,txHash:t}}};if(j&&k){let i={currentSignature:1,currentSignatureReason:e.TransferSignatureReason.TokensTransfer,quote:m,requiredSignatures:1},a=f.signBatch;if(!a)throw new t.SdkError(`One-click batch signer is not available.`,t.ErrorCode.SIGNING_FAILED);let o={chainId:n.caip2ToEip155HexChainId(m.sourceChain.chainId),data:M.data,from:y,gas:void 0,to:M.to,value:M.value,...r.maybe1559(h)};_?.(i);try{let e=(await a([k,o],async e=>x.sendRawTransaction({serializedTransaction:e}),i)).at(-1);if(!e)throw new t.SdkError(`One-click batch signing returned no transaction hashes.`,t.ErrorCode.SIGNING_FAILED);return N(e)}catch(e){if(!g)throw e}}if(A&&k)try{await i.signApprovalAndAssertConfirmed({client:x,evmSigner:f,onStepChange:_,request:k,step:{currentSignature:1,currentSignatureReason:e.TransferSignatureReason.AllowanceApproval,quote:m,requiredSignatures:2}})}catch(e){if(e instanceof i.ApprovalRevertedError)return r.makeFailedTransferFromQuote(m,{environment:u,errorCode:t.ErrorCode.TRANSACTION_REVERTED,errorReason:`ERC20 approval transaction was reverted`});throw e}let P=await d._estimateGasFromSwapResponse({crossChain:E,fromAddress:y,feeUnitsMarginBps:h?.estimateGasMarginBps,sourceClient:x,swap:M}),F={chainId:n.caip2ToEip155HexChainId(m.sourceChain.chainId),data:M.data,from:y,gas:P,to:M.to,value:M.value,...r.maybe1559(h)},I={currentSignature:A?2:1,currentSignatureReason:e.TransferSignatureReason.TokensTransfer,quote:m,requiredSignatures:A?2:1};_?.(I);let L=Date.now();return N(await f.sign(F,async e=>x.sendRawTransaction({serializedTransaction:e}),I),L)}async function _({apiOptions:n,appId:i,environment:a,solanaSigner:d,quote:f,onStepChange:p}){if(!d)throw new t.SdkError(t.ErrorReason.INVALID_PARAMS,t.ErrorCode.INVALID_PARAMS,{details:`solanaSigner is required for Solana transfers but was not provided.`});if(!s.isSolAddress(f.fromAddress))throw new t.SdkError(t.ErrorReason.INVALID_PARAMS,t.ErrorCode.INVALID_PARAMS,{details:`fromAddress is not a valid Solana address.`});let m=c.calculateMarkrMinimumAmountOut({amountOut:f.amountOut,assetOut:f.assetOut,slippageBps:f.slippageBps}),h=c.assetToAddressString(f.assetIn,f.sourceChain.chainId),g=c.assetToAddressString(f.assetOut,f.targetChain.chainId),_=await o.markrSwap(n,{amountIn:f.amountIn.toString(),appId:i,minAmountOut:m.toString(),tokenIn:h,tokenOut:g,userPublicKey:f.fromAddress,uuid:f.id});if(!l.isSolanaSwapResponse(_))throw new t.SdkError(t.ErrorReason.CHAIN_NOT_SUPPORTED,t.ErrorCode.INVALID_PARAMS,{details:`Received non-SVM swap response from Markr, but only SVM swaps are supported for this source chain.`});console.debug(`[Fusion SDK] Original swap transaction (base64):`,_.swapTransaction);let v=await u.refreshSolanaSwapTransactionBlockhash(_.swapTransaction,r.getSolanaRpcForChain({chain:f.sourceChain}));console.debug(`[Fusion SDK] Refreshed swap transaction with new blockhash (base64):`,v);let y={currentSignature:1,currentSignatureReason:e.TransferSignatureReason.TokensTransfer,quote:f,requiredSignatures:1};p?.(y);let b=Date.now(),x=await d.signAndSend({account:f.fromAddress,serializedTx:v},y),S=f.sourceChain.chainId.toLowerCase()!==f.targetChain.chainId.toLowerCase();return{amountIn:f.amountIn,amountOut:f.amountOut,environment:a,fees:f.fees,fromAddress:f.fromAddress,id:f.id,partnerFeeBps:f.partnerFeeBps,sourceAsset:f.assetIn,sourceChain:f.sourceChain,status:`source-pending`,targetAsset:f.assetOut,targetChain:f.targetChain,toAddress:f.toAddress,type:e.ServiceType.MARKR,source:{confirmationCount:0,requiredConfirmationCount:S?2:32,startedAtMs:b,txHash:x}}}function v({approvalRequest:e,requiresApprovalSignature:t,signBatch:n,sourceChainId:r,targetChainId:i}){return a.isEvmNamespace(r)&&a.isEvmNamespace(i)&&r===i&&t&&e!==void 0&&typeof n==`function`}exports.transferAssetFactory=m;
|
|
2
2
|
//# sourceMappingURL=transfer-asset.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-asset.cjs","names":["ServiceType","SdkError","ErrorReason","ErrorCode","HyperliquidChainIds","isSolanaNamespace","isEvmNamespace","calculateMarkrMinimumAmountOut","assetToAddressString","markrSwap","isHyperliquidWithdrawSwapResponse","_executeHyperliquidWithdraw","getEvmClientForChain","isTokenAddressNative","getAdditiveSourceAssetFeeAmount","markrGetSpenderAddress","caip2ToEip155ChainId","erc20Abi","applyFeeUnitsBpsMargin","estimateGasWithRevert","caip2ToEip155HexChainId","isEvmSwapResponse","TransferSignatureReason","makeFailedTransferFromQuote","_estimateGasFromSwapResponse","isSolAddress","isSolanaSwapResponse","refreshSolanaSwapTransactionBlockhash","getSolanaRpcForChain"],"sources":["../../../../src/transfer-service/markr/_handlers/transfer-asset.ts"],"sourcesContent":["import { encodeFunctionData, erc20Abi, isAddress } from 'viem';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { HyperliquidChainIds, ServiceType, TransferSignatureReason } from '../../../constants';\nimport type { Environment } from '../../../constants';\nimport { ErrorCode, ErrorReason, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { EvmSigner, EvmTransactionRequest, SolanaSigner } from '../../../types/signer';\nimport type { Transfer, TransferStepDetails } from '../../../types/transfer';\nimport { caip2ToEip155ChainId, caip2ToEip155HexChainId } from '../../../utils/caip';\nimport { isSolAddress } from '../../../utils/sol-address';\nimport {\n applyFeeUnitsBpsMargin,\n getEvmClientForChain,\n getSolanaRpcForChain,\n makeFailedTransferFromQuote,\n} from '../../_utils';\nimport { estimateGasWithRevert } from '../../_evm-errors';\nimport { markrGetSpenderAddress, markrSwap, type ApiOptions } from '../_api';\nimport {\n assetToAddressString,\n calculateMarkrMinimumAmountOut,\n getAdditiveSourceAssetFeeAmount,\n isTokenAddressNative,\n} from '../_utils';\nimport { isEvmSwapResponse, isHyperliquidWithdrawSwapResponse, isSolanaSwapResponse } from '../_type-guards';\nimport { SOLANA_REQUIRED_CONFIRMATIONS } from '../constants';\nimport { _estimateGasFromSwapResponse } from './estimate-native-fee';\nimport { _executeHyperliquidWithdraw } from './transfer-asset-hyperliquid-withdraw';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport { refreshSolanaSwapTransactionBlockhash } from '../../../utils/solana';\n\nexport interface TransferAssetFactoryConfig {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n evmSigner: EvmSigner;\n solanaSigner?: SolanaSigner;\n}\n\nexport function transferAssetFactory({\n apiOptions,\n appId,\n environment,\n evmSigner,\n solanaSigner,\n}: TransferAssetFactoryConfig): TransferService['transferAsset'] {\n return async ({ quote, gasSettings, fallbackToDefaultOnBatchFailure, onStepChange }) => {\n if (quote.serviceType !== ServiceType.MARKR) {\n throw new SdkError(ErrorReason.INCORRECT_PROVIDER_PROVIDED, ErrorCode.INVALID_PARAMS);\n }\n\n const now = Math.floor(Date.now() / 1_000);\n\n if (quote.expiresAt <= now) {\n throw new SdkError(ErrorReason.QUOTE_EXPIRED, ErrorCode.INVALID_PARAMS);\n }\n\n const sourceChainId = quote.sourceChain.chainId;\n\n if (sourceChainId === HyperliquidChainIds.MAINNET) {\n return _executeHyperliquidWithdrawTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n onStepChange,\n });\n }\n\n if (isSolanaNamespace(sourceChainId)) {\n return _executeSvmTransfer({ apiOptions, appId, environment, solanaSigner, quote, onStepChange });\n }\n\n if (isEvmNamespace(sourceChainId)) {\n return _executeEvmTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n gasSettings,\n fallbackToDefaultOnBatchFailure,\n onStepChange,\n });\n }\n\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: `Unsupported source chain namespace: ${sourceChainId}`,\n });\n };\n}\n\n// ---------------------------------------------------------------------------\n// Hyperliquid withdrawal path — wires `markrSwap` → HL handler\n// ---------------------------------------------------------------------------\n\ninterface HyperliquidWithdrawTransferParams {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n evmSigner: EvmSigner;\n quote: Parameters<TransferService['transferAsset']>[0]['quote'];\n onStepChange?: Parameters<TransferService['transferAsset']>[0]['onStepChange'];\n}\n\nasync function _executeHyperliquidWithdrawTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n onStepChange,\n}: HyperliquidWithdrawTransferParams): Promise<Transfer> {\n const minAmountOut = calculateMarkrMinimumAmountOut({\n amountOut: quote.amountOut,\n assetOut: quote.assetOut,\n slippageBps: quote.slippageBps,\n });\n\n const tokenInAddressString = assetToAddressString(quote.assetIn, quote.sourceChain.chainId);\n const tokenOutAddressString = assetToAddressString(quote.assetOut, quote.targetChain.chainId);\n\n const swap = await markrSwap(apiOptions, {\n amountIn: quote.amountIn.toString(),\n appId,\n minAmountOut: minAmountOut.toString(),\n tokenIn: tokenInAddressString,\n tokenOut: tokenOutAddressString,\n uuid: quote.id,\n });\n\n if (!isHyperliquidWithdrawSwapResponse(swap)) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details:\n 'Expected `hyperliquid-withdraw` swap response from Markr for Hyperliquid source chain, but received a different variant.',\n });\n }\n\n return _executeHyperliquidWithdraw({\n apiOptions,\n environment,\n evmSigner,\n quote,\n swap,\n onStepChange,\n });\n}\n\n// ---------------------------------------------------------------------------\n// EVM transfer path\n// ---------------------------------------------------------------------------\n\ninterface EvmTransferParams {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n evmSigner: EvmSigner;\n quote: Parameters<TransferService['transferAsset']>[0]['quote'];\n gasSettings?: Parameters<TransferService['transferAsset']>[0]['gasSettings'];\n fallbackToDefaultOnBatchFailure?: Parameters<TransferService['transferAsset']>[0]['fallbackToDefaultOnBatchFailure'];\n onStepChange?: Parameters<TransferService['transferAsset']>[0]['onStepChange'];\n}\n\nasync function _executeEvmTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n gasSettings,\n fallbackToDefaultOnBatchFailure,\n onStepChange,\n}: EvmTransferParams): Promise<Transfer> {\n const fromAddress = quote.fromAddress;\n\n if (!isAddress(fromAddress)) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'fromAddress is not a valid EVM address.',\n });\n }\n\n const minAmountOut = calculateMarkrMinimumAmountOut({\n amountOut: quote.amountOut,\n assetOut: quote.assetOut,\n slippageBps: quote.slippageBps,\n });\n\n const sourceClient = getEvmClientForChain({ chain: quote.sourceChain });\n\n const tokenInAddressString = assetToAddressString(quote.assetIn, quote.sourceChain.chainId);\n const tokenOutAddressString = assetToAddressString(quote.assetOut, quote.targetChain.chainId);\n\n if (!isAddress(tokenInAddressString)) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'assetIn address is not a valid EVM address.',\n });\n }\n\n const tokenInAddress = tokenInAddressString;\n const isTokenInNative = isTokenAddressNative(tokenInAddress);\n const isCrossChainSwap = quote.sourceChain.chainId.toLowerCase() !== quote.targetChain.chainId.toLowerCase();\n const allowanceAmount = quote.amountIn + getAdditiveSourceAssetFeeAmount(quote);\n\n const { address: spenderAddress } = await markrGetSpenderAddress(apiOptions, {\n chainId: caip2ToEip155ChainId(quote.sourceChain.chainId),\n crossChainSwap: isCrossChainSwap,\n quoteId: quote.id,\n });\n\n if (!isTokenInNative && !spenderAddress) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: `Missing Markr spender address for source chain ${quote.sourceChain.chainId}.`,\n });\n }\n\n let requiresApprovalSignature = false;\n let approvalRequest: EvmTransactionRequest | undefined;\n\n if (!isTokenInNative && spenderAddress) {\n const allowance = await sourceClient.readContract({\n address: tokenInAddress,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [fromAddress, spenderAddress],\n });\n\n if (allowance < allowanceAmount) {\n requiresApprovalSignature = true;\n\n const approvalData = encodeFunctionData({\n abi: erc20Abi,\n functionName: 'approve',\n args: [spenderAddress, allowanceAmount],\n });\n\n const approvalGasEstimate = await estimateGasWithRevert(\n sourceClient,\n {\n account: fromAddress,\n to: tokenInAddress,\n data: approvalData,\n },\n erc20Abi,\n 'Failed to estimate gas for ERC20 approval transaction.',\n );\n\n const approvalGasWithMargin = applyFeeUnitsBpsMargin(approvalGasEstimate, gasSettings?.estimateGasMarginBps);\n\n approvalRequest = {\n chainId: caip2ToEip155HexChainId(quote.sourceChain.chainId),\n data: approvalData,\n from: fromAddress,\n gas: approvalGasWithMargin,\n to: tokenInAddress,\n value: 0n,\n ...(gasSettings?.maxFeePerGas !== undefined\n ? {\n maxFeePerGas: gasSettings.maxFeePerGas,\n maxPriorityFeePerGas: gasSettings.maxPriorityFeePerGas,\n }\n : null),\n };\n }\n }\n\n const maybeOneClickBatch = isOneClickBatchEligible({\n approvalRequest,\n requiresApprovalSignature,\n signBatch: evmSigner.signBatch,\n sourceChainId: quote.sourceChain.chainId,\n targetChainId: quote.targetChain.chainId,\n });\n\n const swap = await markrSwap(apiOptions, {\n amountIn: quote.amountIn.toString(),\n appId,\n minAmountOut: minAmountOut.toString(),\n tokenIn: tokenInAddressString,\n tokenOut: tokenOutAddressString,\n uuid: quote.id,\n });\n\n if (!isEvmSwapResponse(swap)) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: 'Received non-EVM swap response from Markr, but only EVM swaps are supported for this source chain.',\n });\n }\n\n const makePendingTransfer = (txHash: `0x${string}`, startedAtMs: number = Date.now()): Transfer => {\n const isSameChainTransfer = quote.sourceChain.chainId === quote.targetChain.chainId;\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.MARKR,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: isSameChainTransfer ? 1 : 2,\n startedAtMs,\n txHash,\n },\n };\n };\n\n if (maybeOneClickBatch && approvalRequest) {\n const batchStep: TransferStepDetails = {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: 1,\n };\n\n const signBatch = evmSigner.signBatch;\n\n if (!signBatch) {\n throw new SdkError('One-click batch signer is not available.', ErrorCode.SIGNING_FAILED);\n }\n\n const swapRequest: EvmTransactionRequest = {\n chainId: caip2ToEip155HexChainId(quote.sourceChain.chainId),\n data: swap.data,\n from: fromAddress,\n // Gas is purposely left undefined here.\n // We can't estimate the gas because we aren't executing the\n // approval tx. It's up to the wallet to correctly handle gas estimation.\n gas: undefined,\n to: swap.to,\n value: swap.value,\n ...(gasSettings?.maxFeePerGas !== undefined\n ? {\n maxFeePerGas: gasSettings.maxFeePerGas,\n maxPriorityFeePerGas: gasSettings.maxPriorityFeePerGas,\n }\n : null),\n };\n\n onStepChange?.(batchStep);\n\n try {\n const txHashes = await signBatch(\n [approvalRequest, swapRequest],\n async (signedTxHash) => sourceClient.sendRawTransaction({ serializedTransaction: signedTxHash }),\n batchStep,\n );\n\n const swapTxHash = txHashes.at(-1);\n\n if (!swapTxHash) {\n throw new SdkError('One-click batch signing returned no transaction hashes.', ErrorCode.SIGNING_FAILED);\n }\n\n return makePendingTransfer(swapTxHash);\n } catch (error) {\n if (!fallbackToDefaultOnBatchFailure) {\n throw error;\n }\n }\n }\n\n if (requiresApprovalSignature && approvalRequest) {\n const approvalStep: TransferStepDetails = {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.AllowanceApproval,\n quote,\n requiredSignatures: 2,\n };\n\n onStepChange?.(approvalStep);\n\n const approvalTxHash = await evmSigner.sign(\n approvalRequest,\n async (signedTxHash) => sourceClient.sendRawTransaction({ serializedTransaction: signedTxHash }),\n approvalStep,\n );\n\n const approvalReceipt = await sourceClient.waitForTransactionReceipt({ hash: approvalTxHash });\n\n if (approvalReceipt.status === 'reverted') {\n return makeFailedTransferFromQuote(quote, {\n environment,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'ERC20 approval transaction was reverted',\n });\n }\n }\n\n const swapGasWithMargin = await _estimateGasFromSwapResponse({\n crossChain: isCrossChainSwap,\n fromAddress,\n feeUnitsMarginBps: gasSettings?.estimateGasMarginBps,\n sourceClient,\n swap,\n });\n\n const swapRequest: EvmTransactionRequest = {\n chainId: caip2ToEip155HexChainId(quote.sourceChain.chainId),\n data: swap.data,\n from: fromAddress,\n gas: swapGasWithMargin,\n to: swap.to,\n value: swap.value,\n ...(gasSettings?.maxFeePerGas !== undefined\n ? {\n maxFeePerGas: gasSettings.maxFeePerGas,\n maxPriorityFeePerGas: gasSettings.maxPriorityFeePerGas,\n }\n : null),\n };\n\n const step: TransferStepDetails = {\n currentSignature: requiresApprovalSignature ? 2 : 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: requiresApprovalSignature ? 2 : 1,\n };\n\n onStepChange?.(step);\n\n const startedAtMs = Date.now();\n\n const txHash = await evmSigner.sign(\n swapRequest,\n async (signedTxHash) => sourceClient.sendRawTransaction({ serializedTransaction: signedTxHash }),\n step,\n );\n\n return makePendingTransfer(txHash, startedAtMs);\n}\n\n// ---------------------------------------------------------------------------\n// SVM (Solana) transfer path\n// ---------------------------------------------------------------------------\n\ninterface SvmTransferParams {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n solanaSigner?: SolanaSigner;\n quote: Parameters<TransferService['transferAsset']>[0]['quote'];\n onStepChange?: Parameters<TransferService['transferAsset']>[0]['onStepChange'];\n}\n\nasync function _executeSvmTransfer({\n apiOptions,\n appId,\n environment,\n solanaSigner,\n quote,\n onStepChange,\n}: SvmTransferParams): Promise<Transfer> {\n if (!solanaSigner) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'solanaSigner is required for Solana transfers but was not provided.',\n });\n }\n\n if (!isSolAddress(quote.fromAddress)) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'fromAddress is not a valid Solana address.',\n });\n }\n\n const minAmountOut = calculateMarkrMinimumAmountOut({\n amountOut: quote.amountOut,\n assetOut: quote.assetOut,\n slippageBps: quote.slippageBps,\n });\n\n const tokenInAddressString = assetToAddressString(quote.assetIn, quote.sourceChain.chainId);\n const tokenOutAddressString = assetToAddressString(quote.assetOut, quote.targetChain.chainId);\n\n const swap = await markrSwap(apiOptions, {\n amountIn: quote.amountIn.toString(),\n appId,\n minAmountOut: minAmountOut.toString(),\n tokenIn: tokenInAddressString,\n tokenOut: tokenOutAddressString,\n userPublicKey: quote.fromAddress,\n uuid: quote.id,\n });\n\n if (!isSolanaSwapResponse(swap)) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: 'Received non-SVM swap response from Markr, but only SVM swaps are supported for this source chain.',\n });\n }\n\n // TODO: Cleanup\n console.debug('[Fusion SDK] Original swap transaction (base64):', swap.swapTransaction);\n\n const swapTransactionBase64 = await refreshSolanaSwapTransactionBlockhash(\n swap.swapTransaction,\n getSolanaRpcForChain({ chain: quote.sourceChain }),\n );\n\n // TODO: Cleanup\n console.debug('[Fusion SDK] Refreshed swap transaction with new blockhash (base64):', swapTransactionBase64);\n\n const step: TransferStepDetails = {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: 1,\n };\n\n onStepChange?.(step);\n\n const startedAtMs = Date.now();\n\n const txHash = await solanaSigner.signAndSend(\n {\n account: quote.fromAddress,\n serializedTx: swapTransactionBase64,\n },\n step,\n );\n\n const isCrossChainSwap = quote.sourceChain.chainId.toLowerCase() !== quote.targetChain.chainId.toLowerCase();\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.MARKR,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: isCrossChainSwap ? 2 : SOLANA_REQUIRED_CONFIRMATIONS,\n startedAtMs,\n txHash,\n },\n };\n}\n\n/**\n * Determines whether one-click swap eligibility criteria is met.\n *\n * Only same-chain EVM swaps are currently eligible.\n */\nfunction isOneClickBatchEligible({\n approvalRequest,\n requiresApprovalSignature,\n signBatch,\n sourceChainId,\n targetChainId,\n}: {\n approvalRequest?: EvmTransactionRequest;\n requiresApprovalSignature: boolean;\n signBatch?: EvmSigner['signBatch'];\n sourceChainId: Caip2ChainId;\n targetChainId: Caip2ChainId;\n}): boolean {\n return (\n isEvmNamespace(sourceChainId) &&\n isEvmNamespace(targetChainId) &&\n sourceChainId === targetChainId &&\n requiresApprovalSignature &&\n approvalRequest !== undefined &&\n typeof signBatch === 'function'\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transfer-asset.cjs","names":["ServiceType","SdkError","ErrorReason","ErrorCode","HyperliquidChainIds","isSolanaNamespace","isEvmNamespace","calculateMarkrMinimumAmountOut","assetToAddressString","markrSwap","isHyperliquidWithdrawSwapResponse","_executeHyperliquidWithdraw","getEvmClientForChain","isTokenAddressNative","getAdditiveSourceAssetFeeAmount","markrGetSpenderAddress","caip2ToEip155ChainId","buildErc20ApprovalRequest","caip2ToEip155HexChainId","isEvmSwapResponse","TransferSignatureReason","maybe1559","signApprovalAndAssertConfirmed","ApprovalRevertedError","makeFailedTransferFromQuote","_estimateGasFromSwapResponse","isSolAddress","isSolanaSwapResponse","refreshSolanaSwapTransactionBlockhash","getSolanaRpcForChain"],"sources":["../../../../src/transfer-service/markr/_handlers/transfer-asset.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { HyperliquidChainIds, ServiceType, TransferSignatureReason } from '../../../constants';\nimport type { Environment } from '../../../constants';\nimport { ErrorCode, ErrorReason, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { EvmSigner, EvmTransactionRequest, SolanaSigner } from '../../../types/signer';\nimport type { Transfer, TransferStepDetails } from '../../../types/transfer';\nimport { caip2ToEip155ChainId, caip2ToEip155HexChainId } from '../../../utils/caip';\nimport { isSolAddress } from '../../../utils/sol-address';\nimport { getEvmClientForChain, getSolanaRpcForChain, makeFailedTransferFromQuote, maybe1559 } from '../../_utils';\nimport { ApprovalRevertedError, buildErc20ApprovalRequest, signApprovalAndAssertConfirmed } from '../../_evm-approval';\nimport { markrGetSpenderAddress, markrSwap, type ApiOptions } from '../_api';\nimport {\n assetToAddressString,\n calculateMarkrMinimumAmountOut,\n getAdditiveSourceAssetFeeAmount,\n isTokenAddressNative,\n} from '../_utils';\nimport { isEvmSwapResponse, isHyperliquidWithdrawSwapResponse, isSolanaSwapResponse } from '../_type-guards';\nimport { SOLANA_REQUIRED_CONFIRMATIONS } from '../constants';\nimport { _estimateGasFromSwapResponse } from './estimate-native-fee';\nimport { _executeHyperliquidWithdraw } from './transfer-asset-hyperliquid-withdraw';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport { refreshSolanaSwapTransactionBlockhash } from '../../../utils/solana';\n\nexport interface TransferAssetFactoryConfig {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n evmSigner: EvmSigner;\n solanaSigner?: SolanaSigner;\n}\n\nexport function transferAssetFactory({\n apiOptions,\n appId,\n environment,\n evmSigner,\n solanaSigner,\n}: TransferAssetFactoryConfig): TransferService['transferAsset'] {\n return async ({ quote, gasSettings, fallbackToDefaultOnBatchFailure, onStepChange }) => {\n if (quote.serviceType !== ServiceType.MARKR) {\n throw new SdkError(ErrorReason.INCORRECT_PROVIDER_PROVIDED, ErrorCode.INVALID_PARAMS);\n }\n\n const now = Math.floor(Date.now() / 1_000);\n\n if (quote.expiresAt <= now) {\n throw new SdkError(ErrorReason.QUOTE_EXPIRED, ErrorCode.INVALID_PARAMS);\n }\n\n const sourceChainId = quote.sourceChain.chainId;\n\n if (sourceChainId === HyperliquidChainIds.MAINNET) {\n return _executeHyperliquidWithdrawTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n onStepChange,\n });\n }\n\n if (isSolanaNamespace(sourceChainId)) {\n return _executeSvmTransfer({ apiOptions, appId, environment, solanaSigner, quote, onStepChange });\n }\n\n if (isEvmNamespace(sourceChainId)) {\n return _executeEvmTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n gasSettings,\n fallbackToDefaultOnBatchFailure,\n onStepChange,\n });\n }\n\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: `Unsupported source chain namespace: ${sourceChainId}`,\n });\n };\n}\n\n// ---------------------------------------------------------------------------\n// Hyperliquid withdrawal path — wires `markrSwap` → HL handler\n// ---------------------------------------------------------------------------\n\ninterface HyperliquidWithdrawTransferParams {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n evmSigner: EvmSigner;\n quote: Parameters<TransferService['transferAsset']>[0]['quote'];\n onStepChange?: Parameters<TransferService['transferAsset']>[0]['onStepChange'];\n}\n\nasync function _executeHyperliquidWithdrawTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n onStepChange,\n}: HyperliquidWithdrawTransferParams): Promise<Transfer> {\n const minAmountOut = calculateMarkrMinimumAmountOut({\n amountOut: quote.amountOut,\n assetOut: quote.assetOut,\n slippageBps: quote.slippageBps,\n });\n\n const tokenInAddressString = assetToAddressString(quote.assetIn, quote.sourceChain.chainId);\n const tokenOutAddressString = assetToAddressString(quote.assetOut, quote.targetChain.chainId);\n\n const swap = await markrSwap(apiOptions, {\n amountIn: quote.amountIn.toString(),\n appId,\n minAmountOut: minAmountOut.toString(),\n tokenIn: tokenInAddressString,\n tokenOut: tokenOutAddressString,\n uuid: quote.id,\n });\n\n if (!isHyperliquidWithdrawSwapResponse(swap)) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details:\n 'Expected `hyperliquid-withdraw` swap response from Markr for Hyperliquid source chain, but received a different variant.',\n });\n }\n\n return _executeHyperliquidWithdraw({\n apiOptions,\n environment,\n evmSigner,\n quote,\n swap,\n onStepChange,\n });\n}\n\n// ---------------------------------------------------------------------------\n// EVM transfer path\n// ---------------------------------------------------------------------------\n\ninterface EvmTransferParams {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n evmSigner: EvmSigner;\n quote: Parameters<TransferService['transferAsset']>[0]['quote'];\n gasSettings?: Parameters<TransferService['transferAsset']>[0]['gasSettings'];\n fallbackToDefaultOnBatchFailure?: Parameters<TransferService['transferAsset']>[0]['fallbackToDefaultOnBatchFailure'];\n onStepChange?: Parameters<TransferService['transferAsset']>[0]['onStepChange'];\n}\n\nasync function _executeEvmTransfer({\n apiOptions,\n appId,\n environment,\n evmSigner,\n quote,\n gasSettings,\n fallbackToDefaultOnBatchFailure,\n onStepChange,\n}: EvmTransferParams): Promise<Transfer> {\n const fromAddress = quote.fromAddress;\n\n if (!isAddress(fromAddress)) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'fromAddress is not a valid EVM address.',\n });\n }\n\n const minAmountOut = calculateMarkrMinimumAmountOut({\n amountOut: quote.amountOut,\n assetOut: quote.assetOut,\n slippageBps: quote.slippageBps,\n });\n\n const sourceClient = getEvmClientForChain({ chain: quote.sourceChain });\n\n const tokenInAddressString = assetToAddressString(quote.assetIn, quote.sourceChain.chainId);\n const tokenOutAddressString = assetToAddressString(quote.assetOut, quote.targetChain.chainId);\n\n if (!isAddress(tokenInAddressString)) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'assetIn address is not a valid EVM address.',\n });\n }\n\n const tokenInAddress = tokenInAddressString;\n const isTokenInNative = isTokenAddressNative(tokenInAddress);\n const isCrossChainSwap = quote.sourceChain.chainId.toLowerCase() !== quote.targetChain.chainId.toLowerCase();\n const allowanceAmount = quote.amountIn + getAdditiveSourceAssetFeeAmount(quote);\n\n const { address: spenderAddress } = await markrGetSpenderAddress(apiOptions, {\n chainId: caip2ToEip155ChainId(quote.sourceChain.chainId),\n crossChainSwap: isCrossChainSwap,\n quoteId: quote.id,\n });\n\n if (!isTokenInNative && !spenderAddress) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: `Missing Markr spender address for source chain ${quote.sourceChain.chainId}.`,\n });\n }\n\n const approvalRequest: EvmTransactionRequest | undefined =\n !isTokenInNative && spenderAddress\n ? await buildErc20ApprovalRequest({\n chainIdHex: caip2ToEip155HexChainId(quote.sourceChain.chainId),\n client: sourceClient,\n gasSettings,\n owner: fromAddress,\n requiredAllowance: allowanceAmount,\n spender: spenderAddress,\n token: tokenInAddress,\n })\n : undefined;\n const requiresApprovalSignature = approvalRequest !== undefined;\n\n const maybeOneClickBatch = isOneClickBatchEligible({\n approvalRequest,\n requiresApprovalSignature,\n signBatch: evmSigner.signBatch,\n sourceChainId: quote.sourceChain.chainId,\n targetChainId: quote.targetChain.chainId,\n });\n\n const swap = await markrSwap(apiOptions, {\n amountIn: quote.amountIn.toString(),\n appId,\n minAmountOut: minAmountOut.toString(),\n tokenIn: tokenInAddressString,\n tokenOut: tokenOutAddressString,\n uuid: quote.id,\n });\n\n if (!isEvmSwapResponse(swap)) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: 'Received non-EVM swap response from Markr, but only EVM swaps are supported for this source chain.',\n });\n }\n\n const makePendingTransfer = (txHash: `0x${string}`, startedAtMs: number = Date.now()): Transfer => {\n const isSameChainTransfer = quote.sourceChain.chainId === quote.targetChain.chainId;\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.MARKR,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: isSameChainTransfer ? 1 : 2,\n startedAtMs,\n txHash,\n },\n };\n };\n\n if (maybeOneClickBatch && approvalRequest) {\n const batchStep: TransferStepDetails = {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: 1,\n };\n\n const signBatch = evmSigner.signBatch;\n\n if (!signBatch) {\n throw new SdkError('One-click batch signer is not available.', ErrorCode.SIGNING_FAILED);\n }\n\n const swapRequest: EvmTransactionRequest = {\n chainId: caip2ToEip155HexChainId(quote.sourceChain.chainId),\n data: swap.data,\n from: fromAddress,\n // Gas is purposely left undefined here.\n // We can't estimate the gas because we aren't executing the\n // approval tx. It's up to the wallet to correctly handle gas estimation.\n gas: undefined,\n to: swap.to,\n value: swap.value,\n ...maybe1559(gasSettings),\n };\n\n onStepChange?.(batchStep);\n\n try {\n const txHashes = await signBatch(\n [approvalRequest, swapRequest],\n async (signedTxHash) => sourceClient.sendRawTransaction({ serializedTransaction: signedTxHash }),\n batchStep,\n );\n\n const swapTxHash = txHashes.at(-1);\n\n if (!swapTxHash) {\n throw new SdkError('One-click batch signing returned no transaction hashes.', ErrorCode.SIGNING_FAILED);\n }\n\n return makePendingTransfer(swapTxHash);\n } catch (error) {\n if (!fallbackToDefaultOnBatchFailure) {\n throw error;\n }\n }\n }\n\n if (requiresApprovalSignature && approvalRequest) {\n try {\n await signApprovalAndAssertConfirmed({\n client: sourceClient,\n evmSigner,\n onStepChange,\n request: approvalRequest,\n step: {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.AllowanceApproval,\n quote,\n requiredSignatures: 2,\n },\n });\n } catch (error) {\n // Match the original behavior of \"branch only on the confirmed-then-\n // reverted receipt status\" by discriminating on the dedicated error\n // class — signer rejection / RPC errors fall through to the rethrow.\n if (error instanceof ApprovalRevertedError) {\n return makeFailedTransferFromQuote(quote, {\n environment,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'ERC20 approval transaction was reverted',\n });\n }\n throw error;\n }\n }\n\n const swapGasWithMargin = await _estimateGasFromSwapResponse({\n crossChain: isCrossChainSwap,\n fromAddress,\n feeUnitsMarginBps: gasSettings?.estimateGasMarginBps,\n sourceClient,\n swap,\n });\n\n const swapRequest: EvmTransactionRequest = {\n chainId: caip2ToEip155HexChainId(quote.sourceChain.chainId),\n data: swap.data,\n from: fromAddress,\n gas: swapGasWithMargin,\n to: swap.to,\n value: swap.value,\n ...maybe1559(gasSettings),\n };\n\n const step: TransferStepDetails = {\n currentSignature: requiresApprovalSignature ? 2 : 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: requiresApprovalSignature ? 2 : 1,\n };\n\n onStepChange?.(step);\n\n const startedAtMs = Date.now();\n\n const txHash = await evmSigner.sign(\n swapRequest,\n async (signedTxHash) => sourceClient.sendRawTransaction({ serializedTransaction: signedTxHash }),\n step,\n );\n\n return makePendingTransfer(txHash, startedAtMs);\n}\n\n// ---------------------------------------------------------------------------\n// SVM (Solana) transfer path\n// ---------------------------------------------------------------------------\n\ninterface SvmTransferParams {\n apiOptions: ApiOptions;\n appId: string;\n environment: Environment;\n solanaSigner?: SolanaSigner;\n quote: Parameters<TransferService['transferAsset']>[0]['quote'];\n onStepChange?: Parameters<TransferService['transferAsset']>[0]['onStepChange'];\n}\n\nasync function _executeSvmTransfer({\n apiOptions,\n appId,\n environment,\n solanaSigner,\n quote,\n onStepChange,\n}: SvmTransferParams): Promise<Transfer> {\n if (!solanaSigner) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'solanaSigner is required for Solana transfers but was not provided.',\n });\n }\n\n if (!isSolAddress(quote.fromAddress)) {\n throw new SdkError(ErrorReason.INVALID_PARAMS, ErrorCode.INVALID_PARAMS, {\n details: 'fromAddress is not a valid Solana address.',\n });\n }\n\n const minAmountOut = calculateMarkrMinimumAmountOut({\n amountOut: quote.amountOut,\n assetOut: quote.assetOut,\n slippageBps: quote.slippageBps,\n });\n\n const tokenInAddressString = assetToAddressString(quote.assetIn, quote.sourceChain.chainId);\n const tokenOutAddressString = assetToAddressString(quote.assetOut, quote.targetChain.chainId);\n\n const swap = await markrSwap(apiOptions, {\n amountIn: quote.amountIn.toString(),\n appId,\n minAmountOut: minAmountOut.toString(),\n tokenIn: tokenInAddressString,\n tokenOut: tokenOutAddressString,\n userPublicKey: quote.fromAddress,\n uuid: quote.id,\n });\n\n if (!isSolanaSwapResponse(swap)) {\n throw new SdkError(ErrorReason.CHAIN_NOT_SUPPORTED, ErrorCode.INVALID_PARAMS, {\n details: 'Received non-SVM swap response from Markr, but only SVM swaps are supported for this source chain.',\n });\n }\n\n // TODO: Cleanup\n console.debug('[Fusion SDK] Original swap transaction (base64):', swap.swapTransaction);\n\n const swapTransactionBase64 = await refreshSolanaSwapTransactionBlockhash(\n swap.swapTransaction,\n getSolanaRpcForChain({ chain: quote.sourceChain }),\n );\n\n // TODO: Cleanup\n console.debug('[Fusion SDK] Refreshed swap transaction with new blockhash (base64):', swapTransactionBase64);\n\n const step: TransferStepDetails = {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: 1,\n };\n\n onStepChange?.(step);\n\n const startedAtMs = Date.now();\n\n const txHash = await solanaSigner.signAndSend(\n {\n account: quote.fromAddress,\n serializedTx: swapTransactionBase64,\n },\n step,\n );\n\n const isCrossChainSwap = quote.sourceChain.chainId.toLowerCase() !== quote.targetChain.chainId.toLowerCase();\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.MARKR,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: isCrossChainSwap ? 2 : SOLANA_REQUIRED_CONFIRMATIONS,\n startedAtMs,\n txHash,\n },\n };\n}\n\n/**\n * Determines whether one-click swap eligibility criteria is met.\n *\n * Only same-chain EVM swaps are currently eligible.\n */\nfunction isOneClickBatchEligible({\n approvalRequest,\n requiresApprovalSignature,\n signBatch,\n sourceChainId,\n targetChainId,\n}: {\n approvalRequest?: EvmTransactionRequest;\n requiresApprovalSignature: boolean;\n signBatch?: EvmSigner['signBatch'];\n sourceChainId: Caip2ChainId;\n targetChainId: Caip2ChainId;\n}): boolean {\n return (\n isEvmNamespace(sourceChainId) &&\n isEvmNamespace(targetChainId) &&\n sourceChainId === targetChainId &&\n requiresApprovalSignature &&\n approvalRequest !== undefined &&\n typeof signBatch === 'function'\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{HyperliquidChainIds as e,ServiceType as t,TransferSignatureReason as n}from"../../../constants.js";import{ErrorCode as r,ErrorReason as i,SdkError as a}from"../../../errors.js";import{caip2ToEip155ChainId as o,caip2ToEip155HexChainId as s}from"../../../utils/caip.js";import{
|
|
1
|
+
import{HyperliquidChainIds as e,ServiceType as t,TransferSignatureReason as n}from"../../../constants.js";import{ErrorCode as r,ErrorReason as i,SdkError as a}from"../../../errors.js";import{caip2ToEip155ChainId as o,caip2ToEip155HexChainId as s}from"../../../utils/caip.js";import{getEvmClientForChain as c,getSolanaRpcForChain as l,makeFailedTransferFromQuote as u,maybe1559 as d}from"../../_utils.js";import{ApprovalRevertedError as f,buildErc20ApprovalRequest as p,signApprovalAndAssertConfirmed as m}from"../../_evm-approval.js";import{isEvmNamespace as h,isSolanaNamespace as g}from"../../../_utils/chain.js";import{markrGetSpenderAddress as _,markrSwap as v}from"../_api.js";import{isSolAddress as y}from"../../../utils/sol-address.js";import{assetToAddressString as b,calculateMarkrMinimumAmountOut as x,getAdditiveSourceAssetFeeAmount as S,isTokenAddressNative as C}from"../_utils.js";import{isEvmSwapResponse as w,isHyperliquidWithdrawSwapResponse as T,isSolanaSwapResponse as E}from"../_type-guards.js";import{refreshSolanaSwapTransactionBlockhash as D}from"../../../utils/solana.js";import{_estimateGasFromSwapResponse as O}from"./estimate-native-fee.js";import{_executeHyperliquidWithdraw as k}from"./transfer-asset-hyperliquid-withdraw.js";import{isAddress as A}from"viem";function j({apiOptions:n,appId:o,environment:s,evmSigner:c,solanaSigner:l}){return async({quote:u,gasSettings:d,fallbackToDefaultOnBatchFailure:f,onStepChange:p})=>{if(u.serviceType!==t.MARKR)throw new a(i.INCORRECT_PROVIDER_PROVIDED,r.INVALID_PARAMS);let m=Math.floor(Date.now()/1e3);if(u.expiresAt<=m)throw new a(i.QUOTE_EXPIRED,r.INVALID_PARAMS);let _=u.sourceChain.chainId;if(_===e.MAINNET)return M({apiOptions:n,appId:o,environment:s,evmSigner:c,quote:u,onStepChange:p});if(g(_))return P({apiOptions:n,appId:o,environment:s,solanaSigner:l,quote:u,onStepChange:p});if(h(_))return N({apiOptions:n,appId:o,environment:s,evmSigner:c,quote:u,gasSettings:d,fallbackToDefaultOnBatchFailure:f,onStepChange:p});throw new a(i.CHAIN_NOT_SUPPORTED,r.INVALID_PARAMS,{details:`Unsupported source chain namespace: ${_}`})}}async function M({apiOptions:e,appId:t,environment:n,evmSigner:o,quote:s,onStepChange:c}){let l=x({amountOut:s.amountOut,assetOut:s.assetOut,slippageBps:s.slippageBps}),u=b(s.assetIn,s.sourceChain.chainId),d=b(s.assetOut,s.targetChain.chainId),f=await v(e,{amountIn:s.amountIn.toString(),appId:t,minAmountOut:l.toString(),tokenIn:u,tokenOut:d,uuid:s.id});if(!T(f))throw new a(i.CHAIN_NOT_SUPPORTED,r.INVALID_PARAMS,{details:"Expected `hyperliquid-withdraw` swap response from Markr for Hyperliquid source chain, but received a different variant."});return k({apiOptions:e,environment:n,evmSigner:o,quote:s,swap:f,onStepChange:c})}async function N({apiOptions:e,appId:l,environment:h,evmSigner:g,quote:y,gasSettings:T,fallbackToDefaultOnBatchFailure:E,onStepChange:D}){let k=y.fromAddress;if(!A(k))throw new a(i.INVALID_PARAMS,r.INVALID_PARAMS,{details:`fromAddress is not a valid EVM address.`});let j=x({amountOut:y.amountOut,assetOut:y.assetOut,slippageBps:y.slippageBps}),M=c({chain:y.sourceChain}),N=b(y.assetIn,y.sourceChain.chainId),P=b(y.assetOut,y.targetChain.chainId);if(!A(N))throw new a(i.INVALID_PARAMS,r.INVALID_PARAMS,{details:`assetIn address is not a valid EVM address.`});let I=N,L=C(I),R=y.sourceChain.chainId.toLowerCase()!==y.targetChain.chainId.toLowerCase(),z=y.amountIn+S(y),{address:B}=await _(e,{chainId:o(y.sourceChain.chainId),crossChainSwap:R,quoteId:y.id});if(!L&&!B)throw new a(i.CHAIN_NOT_SUPPORTED,r.INVALID_PARAMS,{details:`Missing Markr spender address for source chain ${y.sourceChain.chainId}.`});let V=!L&&B?await p({chainIdHex:s(y.sourceChain.chainId),client:M,gasSettings:T,owner:k,requiredAllowance:z,spender:B,token:I}):void 0,H=V!==void 0,U=F({approvalRequest:V,requiresApprovalSignature:H,signBatch:g.signBatch,sourceChainId:y.sourceChain.chainId,targetChainId:y.targetChain.chainId}),W=await v(e,{amountIn:y.amountIn.toString(),appId:l,minAmountOut:j.toString(),tokenIn:N,tokenOut:P,uuid:y.id});if(!w(W))throw new a(i.CHAIN_NOT_SUPPORTED,r.INVALID_PARAMS,{details:`Received non-EVM swap response from Markr, but only EVM swaps are supported for this source chain.`});let G=(e,n=Date.now())=>{let r=y.sourceChain.chainId===y.targetChain.chainId;return{amountIn:y.amountIn,amountOut:y.amountOut,environment:h,fees:y.fees,fromAddress:y.fromAddress,id:y.id,partnerFeeBps:y.partnerFeeBps,sourceAsset:y.assetIn,sourceChain:y.sourceChain,status:`source-pending`,targetAsset:y.assetOut,targetChain:y.targetChain,toAddress:y.toAddress,type:t.MARKR,source:{confirmationCount:0,requiredConfirmationCount:r?1:2,startedAtMs:n,txHash:e}}};if(U&&V){let e={currentSignature:1,currentSignatureReason:n.TokensTransfer,quote:y,requiredSignatures:1},t=g.signBatch;if(!t)throw new a(`One-click batch signer is not available.`,r.SIGNING_FAILED);let i={chainId:s(y.sourceChain.chainId),data:W.data,from:k,gas:void 0,to:W.to,value:W.value,...d(T)};D?.(e);try{let n=(await t([V,i],async e=>M.sendRawTransaction({serializedTransaction:e}),e)).at(-1);if(!n)throw new a(`One-click batch signing returned no transaction hashes.`,r.SIGNING_FAILED);return G(n)}catch(e){if(!E)throw e}}if(H&&V)try{await m({client:M,evmSigner:g,onStepChange:D,request:V,step:{currentSignature:1,currentSignatureReason:n.AllowanceApproval,quote:y,requiredSignatures:2}})}catch(e){if(e instanceof f)return u(y,{environment:h,errorCode:r.TRANSACTION_REVERTED,errorReason:`ERC20 approval transaction was reverted`});throw e}let K=await O({crossChain:R,fromAddress:k,feeUnitsMarginBps:T?.estimateGasMarginBps,sourceClient:M,swap:W}),q={chainId:s(y.sourceChain.chainId),data:W.data,from:k,gas:K,to:W.to,value:W.value,...d(T)},J={currentSignature:H?2:1,currentSignatureReason:n.TokensTransfer,quote:y,requiredSignatures:H?2:1};D?.(J);let Y=Date.now();return G(await g.sign(q,async e=>M.sendRawTransaction({serializedTransaction:e}),J),Y)}async function P({apiOptions:e,appId:o,environment:s,solanaSigner:c,quote:u,onStepChange:d}){if(!c)throw new a(i.INVALID_PARAMS,r.INVALID_PARAMS,{details:`solanaSigner is required for Solana transfers but was not provided.`});if(!y(u.fromAddress))throw new a(i.INVALID_PARAMS,r.INVALID_PARAMS,{details:`fromAddress is not a valid Solana address.`});let f=x({amountOut:u.amountOut,assetOut:u.assetOut,slippageBps:u.slippageBps}),p=b(u.assetIn,u.sourceChain.chainId),m=b(u.assetOut,u.targetChain.chainId),h=await v(e,{amountIn:u.amountIn.toString(),appId:o,minAmountOut:f.toString(),tokenIn:p,tokenOut:m,userPublicKey:u.fromAddress,uuid:u.id});if(!E(h))throw new a(i.CHAIN_NOT_SUPPORTED,r.INVALID_PARAMS,{details:`Received non-SVM swap response from Markr, but only SVM swaps are supported for this source chain.`});console.debug(`[Fusion SDK] Original swap transaction (base64):`,h.swapTransaction);let g=await D(h.swapTransaction,l({chain:u.sourceChain}));console.debug(`[Fusion SDK] Refreshed swap transaction with new blockhash (base64):`,g);let _={currentSignature:1,currentSignatureReason:n.TokensTransfer,quote:u,requiredSignatures:1};d?.(_);let S=Date.now(),C=await c.signAndSend({account:u.fromAddress,serializedTx:g},_),w=u.sourceChain.chainId.toLowerCase()!==u.targetChain.chainId.toLowerCase();return{amountIn:u.amountIn,amountOut:u.amountOut,environment:s,fees:u.fees,fromAddress:u.fromAddress,id:u.id,partnerFeeBps:u.partnerFeeBps,sourceAsset:u.assetIn,sourceChain:u.sourceChain,status:`source-pending`,targetAsset:u.assetOut,targetChain:u.targetChain,toAddress:u.toAddress,type:t.MARKR,source:{confirmationCount:0,requiredConfirmationCount:w?2:32,startedAtMs:S,txHash:C}}}function F({approvalRequest:e,requiresApprovalSignature:t,signBatch:n,sourceChainId:r,targetChainId:i}){return h(r)&&h(i)&&r===i&&t&&e!==void 0&&typeof n==`function`}export{j as transferAssetFactory};
|
|
2
2
|
//# sourceMappingURL=transfer-asset.js.map
|