@funkit/fun-relay 0.1.5 → 0.1.7

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @funkit/fun-relay
2
2
 
3
+ ## 0.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 9cc9c7f: refactor: reduce latency of usd estimation
8
+
9
+ ## 0.1.6
10
+
11
+ ### Patch Changes
12
+
13
+ - a6ce5cb: refactor: deprecate getPrice call
14
+
3
15
  ## 0.1.5
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -212,6 +212,29 @@ async function getRelayAssetPriceInfo({
212
212
  // src/quote.ts
213
213
  var import_viem = require("viem");
214
214
 
215
+ // src/currency.ts
216
+ var import_relay_sdk5 = require("@reservoir0x/relay-sdk");
217
+ async function getRelayAssetInfo({
218
+ chainId,
219
+ address
220
+ }) {
221
+ const url = `${import_relay_sdk5.MAINNET_RELAY_API}/currencies/v2`;
222
+ const body = {
223
+ chainIds: [chainId],
224
+ address
225
+ };
226
+ const response = await fetch(url, {
227
+ method: "POST",
228
+ headers: { "Content-Type": "application/json" },
229
+ body: JSON.stringify(body)
230
+ });
231
+ if (!response.ok) {
232
+ throw Error(response.statusText);
233
+ }
234
+ const data = await response.json();
235
+ return data?.[0];
236
+ }
237
+
215
238
  // src/utils.ts
216
239
  function convertFunToRelayTokenAddress(address) {
217
240
  if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {
@@ -243,6 +266,34 @@ function isRelayExecutionTerminalStatus(info) {
243
266
  }
244
267
 
245
268
  // src/quote.ts
269
+ async function getQuoteEstUsdValue({
270
+ tokenChainId,
271
+ tokenAddress,
272
+ tokenAmountBaseUnit,
273
+ logger
274
+ }) {
275
+ try {
276
+ const [tokenPriceRes, tokenInfoRes] = await Promise.all([
277
+ getRelayAssetPriceInfo({
278
+ chainId: tokenChainId,
279
+ address: convertFunToRelayTokenAddress(tokenAddress)
280
+ }),
281
+ getRelayAssetInfo({
282
+ chainId: tokenChainId,
283
+ address: convertFunToRelayTokenAddress(tokenAddress)
284
+ })
285
+ ]);
286
+ const price = tokenPriceRes.price;
287
+ const decimals = tokenInfoRes.decimals;
288
+ const absoluteAmount = BigInt(tokenAmountBaseUnit) / BigInt(10 ** decimals);
289
+ return Number(price) * Number(absoluteAmount);
290
+ } catch (err) {
291
+ logger.error("getQuoteEstUsdValueError", {
292
+ message: `Failed to get USD value for token ${tokenAddress} on chain ${tokenChainId}: ${err instanceof Error ? err.message : JSON.stringify(err)}. Falling back to 0 USD.`
293
+ });
294
+ return 0;
295
+ }
296
+ }
246
297
  async function getRelayQuote({
247
298
  logger,
248
299
  ...params
@@ -260,8 +311,6 @@ async function getRelayQuote({
260
311
  } = params;
261
312
  try {
262
313
  const relayClient = getRelayClient();
263
- const isExactIn = params.tradeType === "EXACT_INPUT";
264
- const tokenAmountBaseUnit = isExactIn ? params.fromTokenAmountBaseUnit : params.toTokenAmountBaseUnit;
265
314
  const txs = actionParams?.map((action) => {
266
315
  const data = (0, import_viem.encodeFunctionData)({
267
316
  abi: action.contractAbi,
@@ -274,18 +323,16 @@ async function getRelayQuote({
274
323
  value: String(action.value ?? 0n)
275
324
  };
276
325
  });
277
- const priceInfo = await relayClient.actions.getPrice({
278
- originChainId: Number(fromChainId),
279
- originCurrency: convertFunToRelayTokenAddress(fromTokenAddress),
280
- destinationChainId: Number(toChainId),
281
- destinationCurrency: convertFunToRelayTokenAddress(toTokenAddress),
282
- amount: tokenAmountBaseUnit.toString(),
283
- tradeType: params.tradeType,
284
- user: userAddress,
285
- recipient: recipientAddress,
286
- options
326
+ const isExactIn = params.tradeType === "EXACT_INPUT";
327
+ const queryTokenAmountBaseUnit = isExactIn ? params.fromTokenAmountBaseUnit : params.toTokenAmountBaseUnit;
328
+ const queryTokenAddress = isExactIn ? fromTokenAddress : toTokenAddress;
329
+ const queryTokenChainId = isExactIn ? fromChainId : toChainId;
330
+ const estUsdValue = await getQuoteEstUsdValue({
331
+ tokenChainId: queryTokenChainId,
332
+ tokenAddress: queryTokenAddress,
333
+ tokenAmountBaseUnit: queryTokenAmountBaseUnit.toString(),
334
+ logger
287
335
  });
288
- const estUsdValue = priceInfo.details?.currencyIn?.amountUsd;
289
336
  const feeInfo = await getFunRelayFees({
290
337
  fromTokenAddress,
291
338
  fromChainId,
@@ -297,9 +344,9 @@ async function getRelayQuote({
297
344
  const appFeeBp = feeInfo.b + feeInfo.v;
298
345
  logger.info("getRelayQuoteParams", {
299
346
  ...params,
300
- tokenAmountBaseUnit,
347
+ queryTokenAmountBaseUnit,
301
348
  txs,
302
- priceInfo,
349
+ estUsdValue,
303
350
  feeInfo,
304
351
  appFeeBp
305
352
  });
@@ -308,7 +355,7 @@ async function getRelayQuote({
308
355
  toChainId: Number(toChainId),
309
356
  currency: convertFunToRelayTokenAddress(fromTokenAddress),
310
357
  toCurrency: convertFunToRelayTokenAddress(toTokenAddress),
311
- amount: tokenAmountBaseUnit.toString(),
358
+ amount: queryTokenAmountBaseUnit.toString(),
312
359
  recipient: recipientAddress,
313
360
  tradeType: params.tradeType,
314
361
  user: userAddress,
@@ -367,9 +414,9 @@ async function getRelayQuote({
367
414
  // TODO: ?
368
415
  lpFeeUsd: totalLpFeesUsd,
369
416
  metadata: {
370
- fromAmountBaseUnit: params.tradeType === "EXACT_INPUT" ? tokenAmountBaseUnit.toString() : relayQuote.details.currencyIn.amount ?? "0",
417
+ fromAmountBaseUnit: isExactIn ? queryTokenAmountBaseUnit.toString() : relayQuote.details.currencyIn.amount ?? "0",
371
418
  relayQuote,
372
- toAmountBaseUnit: params.tradeType === "EXACT_INPUT" ? relayQuote.details.currencyOut.amount ?? "0" : tokenAmountBaseUnit.toString()
419
+ toAmountBaseUnit: isExactIn ? relayQuote.details.currencyOut.amount ?? "0" : queryTokenAmountBaseUnit.toString()
373
420
  }
374
421
  };
375
422
  } catch (err) {
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../index.ts", "../src/client.ts", "../src/types.ts", "../src/constants.ts", "../src/execution.ts", "../src/fees.ts", "../src/price.ts", "../src/quote.ts", "../src/utils.ts"],
4
- "sourcesContent": ["export {\n getRelayClient,\n initializeRelayClient,\n type InitializeRelayClientParams,\n} from './src/client'\nexport {\n FUN_RELAY_REFERRER,\n FUN_RELAY_REVENUE_WALLET,\n RELAY_TERMINAL_STATUSES,\n} from './src/constants'\nexport {\n type ExecuteRelayQuoteParams,\n executeRelayQuote,\n getRelayExecutionInfo,\n} from './src/execution'\nexport { parseRelayFees } from './src/fees'\nexport { getRelayAssetPriceInfo } from './src/price'\nexport {\n type GetRelayQuoteParams,\n getRelayQuote,\n type RelayQuote,\n} from './src/quote'\nexport {\n getRelayExecutionRefundState,\n getRelayExecutionState,\n isRelayExecutionTerminalStatus,\n convertFunToRelayTokenAddress,\n} from './src/utils'\nexport {\n LogLevel,\n type RelayExecutionInfo,\n type RelayExecutionStatus,\n type RelayTokenPriceInfo,\n} from './src/types'\n", "import {\n MAINNET_RELAY_API,\n type RelayClient,\n type RelayClientOptions,\n convertViemChainToRelayChain,\n createClient,\n getClient,\n} from '@reservoir0x/relay-sdk'\nimport type { Chain } from 'viem'\nimport type { Logger } from './types'\n\nexport type InitializeRelayClientParams = Omit<\n RelayClientOptions,\n 'baseApiUrl' | 'chains' | 'logger'\n> & {\n chains: Chain[]\n logger: Logger\n}\n\n/**\n * Initializes a global instance of the RelayClient\n * https://docs.relay.link/references/sdk/createClient\n */\nexport function initializeRelayClient({\n chains,\n logger,\n ...options\n}: InitializeRelayClientParams): RelayClient {\n return createClient({\n ...options,\n baseApiUrl: MAINNET_RELAY_API,\n chains: chains.map(convertViemChainToRelayChain),\n logger: (message) => {\n logger.info('[RelayClient]:', message)\n },\n })\n}\n\n/**\n * Gets the global instance of the RelayClient\n */\nexport function getRelayClient(): RelayClient {\n const client = getClient()\n\n if (!client) {\n throw new Error('Relay client is not defined')\n }\n\n return client\n}\n", "import { LogLevel } from '@reservoir0x/relay-sdk'\nimport type { Abi, Address } from 'viem'\n\nexport { LogLevel }\n\n// https://docs.relay.link/references/api/get-intents-status-v2\nexport interface RelayExecutionInfo {\n status: RelayExecutionStatus\n details: string\n /** Incoming transaction hashes */\n inTxHashes: string[]\n /** Outgoing transaction hashes */\n txHashes: string[]\n /** The last timestamp the data was updated in milliseconds */\n time: number\n originChainId: number\n destinationChainId: number\n}\n\n// https://docs.relay.link/references/api/get-token-price\nexport interface RelayTokenPriceInfo {\n price: number\n}\n\n//// The types below are duplicated from @funkit/api-base atm, but this package should be used in BE as well\n//// TODO: Are we fine with BE importing @funkit/api-base and (by extension) @funkit/utils?\n//// See https://linear.app/funxyz/issue/PE-1342/sdk-extract-domainsrelayts-to-a-new-package#comment-d487d533\n\nexport interface Logger {\n error(message: string, data?: object): void\n info(message: string, data?: object): void\n}\n\n// Reference: https://github.com/reservoirprotocol/relay-kit/blob/211c645f9702a3b459ff545aa4e2e9d536c38455/packages/sdk/src/types/Execute.ts#L54-L61\nexport enum RelayExecutionStatus {\n DELAYED = 'delayed',\n FAILURE = 'failure',\n PENDING = 'pending',\n REFUND = 'refund',\n SUCCESS = 'success',\n WAITING = 'waiting',\n UNKNOWN = 'unknown',\n}\n\nexport interface ApiFunkitCheckoutActionParams {\n contractAbi: Abi\n contractAddress: Address\n functionName: string\n functionArgs: unknown[]\n value?: bigint\n}\n\nexport enum CheckoutRefundState {\n INITIATED = 'INITIATED',\n ERROR = 'ERROR',\n REFUNDED = 'REFUNDED',\n PROCEEDED = 'PROCEEDED',\n WAITING_FOR_FULFILLMENT = 'WAITING_FOR_FULFILLMENT',\n FULFILLED = 'FULFILLED',\n}\n\n// Reference from api server: https://github.com/fun-xyz/fun-api-server/blob/main/src/tables/FunWalletCheckout.ts#L11C1-L21C2\nexport enum CheckoutState {\n // In-progress States\n FROM_UNFUNDED = 'FROM_UNFUNDED',\n FROM_FUNDED = 'FROM_FUNDED',\n FROM_POOLED = 'FROM_POOLED',\n TO_UNFUNDED = 'TO_UNFUNDED',\n TO_FUNDED = 'TO_FUNDED',\n TO_POOLED = 'TO_POOLED',\n TO_READY = 'TO_READY',\n PENDING_RECEIVAL = 'PENDING_RECEIVAL',\n // Terminal States\n COMPLETED = 'COMPLETED',\n CHECKOUT_ERROR = 'CHECKOUT_ERROR',\n EXPIRED = 'EXPIRED',\n CANCELLED = 'CANCELLED',\n}\n\n// The response of the actual /checkout/quote api\nexport type CheckoutApiQuoteResponse = {\n quoteId: string\n estTotalFromAmountBaseUnit: string\n estSubtotalFromAmountBaseUnit: string\n estFeesFromAmountBaseUnit: string\n fromTokenAddress: Address\n estFeesUsd: number\n estSubtotalUsd: number\n estTotalUsd: number\n estCheckoutTimeMs: number\n estMarketMakerGasUsd: number\n lpFeePercentage: number\n lpFeeUsd: number\n}\n\n// The formatted response quote interface from the core sdk\nexport type CheckoutQuoteResponse = CheckoutApiQuoteResponse & {\n estTotalFromAmount: string\n estSubtotalFromAmount: string\n estFeesFromAmount: string\n\n // Any additional fields purely for frontend use\n metadata?: { [key: string]: unknown }\n}\n", "import type { Address } from 'viem'\nimport { RelayExecutionStatus } from './types'\n\n/**\n * Fake address for a chain's native currency used by Funkit\n */\nexport const FUNKIT_NATIVE_TOKEN =\n '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' satisfies Address\n\n/**\n * Fake address for a chain's native currency used by Relay\n */\nexport const RELAY_NATIVE_TOKEN =\n '0x0000000000000000000000000000000000000000' satisfies Address\n\n/**\n * Wallet that receives the app fees collected by Relay\n */\nexport const FUN_RELAY_REVENUE_WALLET =\n '0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E' satisfies Address\n\n/**\n * Referred field in Relay quote\n */\nexport const FUN_RELAY_REFERRER = 'funxyz'\n\n/**\n * Buffer added to Relay's time estimate (which sometimes is 0)\n */\nexport const RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25_000 // 25 seconds\n\nexport const RELAY_TERMINAL_STATUSES: RelayExecutionStatus[] = [\n RelayExecutionStatus.REFUND,\n RelayExecutionStatus.FAILURE,\n RelayExecutionStatus.SUCCESS,\n]\n", "import {\n type Execute,\n MAINNET_RELAY_API,\n type ProgressData,\n} from '@reservoir0x/relay-sdk'\nimport type { Hex, WalletClient } from 'viem'\nimport { getRelayClient } from './client'\nimport type { Logger, RelayExecutionInfo } from './types'\n\nexport type RelayExecutionStep = ProgressData['currentStep'] & {}\n\nexport interface ExecuteRelayQuoteParams {\n logger: Logger\n onConfirmed: (txHash: Hex) => Promise<void>\n onError: (error: Error) => Promise<void>\n onProgress?: (step: RelayExecutionStep | null) => void\n relayQuote: Execute\n walletClient: WalletClient\n}\n\nexport async function executeRelayQuote({\n logger,\n onConfirmed,\n onError,\n onProgress,\n relayQuote,\n walletClient,\n}: ExecuteRelayQuoteParams) {\n await getRelayClient().actions.execute({\n quote: relayQuote,\n wallet: walletClient,\n onProgress: async ({\n steps,\n fees,\n breakdown,\n currentStep,\n currentStepItem,\n txHashes,\n details,\n error,\n }) => {\n const logPrefix = 'onRelayProgress'\n logger.info(`${logPrefix}:params`, {\n steps,\n currentStep,\n fees,\n breakdown,\n currentStepItem,\n txHashes,\n details,\n error,\n })\n\n onProgress?.(currentStep ?? null)\n\n if (error) {\n logger.info(`${logPrefix}:errorDetected`, error)\n await onError(error).catch((e) => {\n logger.error(`${logPrefix}:onErrorFailed`, e)\n })\n } else if (\n // We can redirect as soon as all the required user steps are done\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1748381169792379\n txHashes &&\n txHashes.length > 0 &&\n txHashes.length === steps.length\n ) {\n logger.info(`${logPrefix}:completed`, txHashes)\n // Can we assume its completed here?\n // Use first txHash as the main txHash in fun DE table\n await onConfirmed(txHashes[0].txHash as Hex).catch((e) => {\n logger.error(`${logPrefix}:onConfirmedFailed`, e)\n })\n }\n },\n })\n}\n\nexport async function getRelayExecutionInfo(\n requestId: string,\n): Promise<RelayExecutionInfo> {\n const url = `${MAINNET_RELAY_API}/intents/status/v2?requestId=${requestId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayExecutionInfo\n}\n", "import type { CallFees } from '@reservoir0x/relay-sdk'\nimport type { Logger } from './types'\n\nexport interface FunRelayFeeItem {\n b: number\n v: number\n}\n\nexport async function getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue,\n clientId,\n}: {\n fromTokenAddress: string\n fromChainId: string\n toTokenAddress: string\n toChainId: string\n estUsdValue: number\n clientId: string\n}): Promise<FunRelayFeeItem> {\n const url = `https://frog.fun.xyz/api/fee?fromTokenAddress=${fromTokenAddress}&fromChainId=${fromChainId}&toTokenAddress=${toTokenAddress}&toChainId=${toChainId}&estUsdValue=${estUsdValue}&clientId=${clientId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data\n}\n\nexport function parseRelayFees({\n fees,\n logger,\n}: {\n fees: CallFees | undefined\n logger: Logger\n}) {\n // Gas fees, denominated in source chain native token\n const relayGasFeesUsd = Number.parseFloat(fees?.gas?.amountUsd || '0')\n\n // App fees, denominated in source chain token\n const funLpFeesUsd = Number.parseFloat(fees?.app?.amountUsd || '0')\n const funLpFeesFromAmount = Number.parseFloat(\n fees?.app?.amountFormatted || '0',\n )\n const funLpFeesFromAmountBaseUnit = BigInt(fees?.app?.amount || '0')\n\n // Relay fees, denominated in source chain token\n const relayLpFeesUsd =\n Number.parseFloat(fees?.relayer?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerGas?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerService?.amountUsd || '0')\n const relayLpFeesFromAmount =\n Number.parseFloat(fees?.relayer?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerGas?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerService?.amountFormatted || '0')\n const relayLpFeesFromAmountBaseUnit =\n BigInt(fees?.relayer?.amount || '0') +\n BigInt(fees?.relayerGas?.amount || '0') +\n BigInt(fees?.relayerService?.amount || '0')\n\n const totalLpFeesUsd = funLpFeesUsd + relayLpFeesUsd\n const totalLpFeesFromAmount = funLpFeesFromAmount + relayLpFeesFromAmount\n const totalLpFeesFromAmountBaseUnit =\n funLpFeesFromAmountBaseUnit + relayLpFeesFromAmountBaseUnit\n\n logger.info('parseRelayFees', {\n relayGasFeesUsd,\n funLpFeesUsd,\n funLpFeesFromAmount,\n funLpFeesFromAmountBaseUnit,\n relayLpFeesUsd,\n relayLpFeesFromAmount,\n relayLpFeesFromAmountBaseUnit,\n totalLpFeesUsd,\n totalLpFeesFromAmount,\n totalLpFeesFromAmountBaseUnit,\n })\n\n return {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd: relayGasFeesUsd + totalLpFeesUsd,\n totalFeesFromAmount: totalLpFeesFromAmount,\n totalFeesFromAmountBaseUnit: totalLpFeesFromAmountBaseUnit,\n }\n}\n", "import { MAINNET_RELAY_API } from '@reservoir0x/relay-sdk'\nimport type { RelayTokenPriceInfo } from './types'\n\nexport async function getRelayAssetPriceInfo({\n chainId,\n address,\n}: {\n chainId: string\n address: string\n}): Promise<RelayTokenPriceInfo> {\n const url = `${MAINNET_RELAY_API}/currencies/token/price?chainId=${chainId}&address=${address}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayTokenPriceInfo\n}\n", "import type { Execute, GetQuoteParameters } from '@reservoir0x/relay-sdk'\nimport { type Address, encodeFunctionData } from 'viem'\nimport { getRelayClient } from './client'\nimport {\n FUN_RELAY_REFERRER,\n FUN_RELAY_REVENUE_WALLET,\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n} from './constants'\nimport { getFunRelayFees, parseRelayFees } from './fees'\nimport type {\n ApiFunkitCheckoutActionParams,\n CheckoutQuoteResponse,\n Logger,\n} from './types'\nimport { convertFunToRelayTokenAddress } from './utils'\n\ntype RelayQuoteOptions = GetQuoteParameters['options'] & {}\n\nexport type GetRelayQuoteParams = {\n actionParams?: ApiFunkitCheckoutActionParams[]\n fromChainId: string\n fromTokenAddress: Address\n logger: Logger\n /**\n * {@link getRelayQuote} already sets {@link RelayQuoteOptions.appFees|appFees} and {@link RelayQuoteOptions.referrer|referrer}.\n * Only include them if you wish to override.\n */\n options?: RelayQuoteOptions\n recipientAddress: Address | undefined\n toChainId: string\n toTokenAddress: Address\n tradeType: 'EXACT_INPUT' | 'EXACT_OUTPUT'\n userAddress: Address | undefined\n clientId: string\n} & (\n | {\n fromTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_INPUT'\n }\n | {\n toTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_OUTPUT'\n }\n)\n\nexport type RelayQuote = CheckoutQuoteResponse & {\n /** Required for EXACT_INPUT checkouts */\n finalToAmountBaseUnit: string\n metadata: {\n fromAmountBaseUnit: string\n relayQuote: Execute\n toAmountBaseUnit: string\n }\n}\n\nexport async function getRelayQuote({\n logger,\n ...params\n}: GetRelayQuoteParams): Promise<RelayQuote> {\n const {\n actionParams,\n fromChainId,\n fromTokenAddress,\n options,\n recipientAddress,\n toChainId,\n toTokenAddress,\n userAddress,\n clientId,\n } = params\n\n try {\n const relayClient = getRelayClient()\n\n const isExactIn = params.tradeType === 'EXACT_INPUT'\n const tokenAmountBaseUnit = isExactIn\n ? params.fromTokenAmountBaseUnit\n : params.toTokenAmountBaseUnit\n\n const txs = actionParams?.map((action) => {\n const data = encodeFunctionData({\n abi: action.contractAbi,\n args: action.functionArgs,\n functionName: action.functionName,\n })\n\n return {\n data,\n to: action.contractAddress,\n value: String(action.value ?? 0n),\n }\n })\n\n const priceInfo = await relayClient.actions.getPrice({\n originChainId: Number(fromChainId),\n originCurrency: convertFunToRelayTokenAddress(fromTokenAddress),\n destinationChainId: Number(toChainId),\n destinationCurrency: convertFunToRelayTokenAddress(toTokenAddress),\n amount: tokenAmountBaseUnit.toString(),\n tradeType: params.tradeType,\n user: userAddress,\n recipient: recipientAddress,\n options,\n })\n\n const estUsdValue = priceInfo.details?.currencyIn?.amountUsd\n\n const feeInfo = await getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue: Number(estUsdValue) || 0,\n clientId,\n })\n const appFeeBp = feeInfo.b + feeInfo.v\n\n logger.info('getRelayQuoteParams', {\n ...params,\n tokenAmountBaseUnit,\n txs,\n priceInfo,\n feeInfo,\n appFeeBp,\n })\n\n // Get the relay quote\n const relayQuote = await relayClient.actions.getQuote({\n chainId: Number(fromChainId),\n toChainId: Number(toChainId),\n currency: convertFunToRelayTokenAddress(fromTokenAddress),\n toCurrency: convertFunToRelayTokenAddress(toTokenAddress),\n amount: tokenAmountBaseUnit.toString(),\n recipient: recipientAddress,\n tradeType: params.tradeType,\n user: userAddress,\n ...(txs && { txs }),\n options: {\n referrer: clientId\n ? `${FUN_RELAY_REFERRER}|${clientId}`\n : FUN_RELAY_REFERRER,\n appFees: [\n {\n fee: appFeeBp.toString(),\n recipient: FUN_RELAY_REVENUE_WALLET,\n },\n ],\n ...options,\n },\n })\n\n // TODO: Handling for no route response\n\n logger.info('relayQuote', relayQuote)\n\n const estSubtotalUsd = Number(\n relayQuote.details?.currencyOut?.amountUsd || 0,\n )\n const estTotalUsd = Number(relayQuote.details?.currencyIn?.amountUsd || 0)\n // Get how much fromAmount is needed for the quote\n const fromAmountString =\n relayQuote.details?.currencyIn?.amountFormatted || '0'\n const fromAmountBaseUnitString =\n relayQuote.details?.currencyIn?.amount || '0'\n\n // RequestID will be consistent across steps in the quote\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1747774944603209\n const relayRequestId = relayQuote.steps[0]?.requestId\n\n // TODO: Verify with relay team if this is possible?\n if (!relayRequestId) {\n throw new Error('Relay quote does not contain a requestId')\n }\n\n // TODO: Verify with relay team if this is possible?\n if (!relayQuote.details?.currencyIn || !relayQuote.details?.currencyOut) {\n throw new Error('Relay quote does not contain trade details')\n }\n\n const {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd,\n totalFeesFromAmount,\n totalFeesFromAmountBaseUnit,\n } = parseRelayFees({ fees: relayQuote.fees, logger })\n\n const estSubtotalFromAmount = (\n Number.parseFloat(fromAmountString) - totalFeesFromAmount\n ).toString()\n\n const estSubtotalFromAmountBaseUnit = (\n BigInt(fromAmountBaseUnitString) - totalFeesFromAmountBaseUnit\n ).toString()\n\n return {\n quoteId: relayRequestId,\n estCheckoutTimeMs:\n (relayQuote.details.timeEstimate || 0) * 1000 +\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n estFeesFromAmount: totalFeesFromAmount.toString(),\n estFeesFromAmountBaseUnit: totalFeesFromAmountBaseUnit.toString(),\n estFeesUsd: totalFeesUsd,\n estMarketMakerGasUsd: relayGasFeesUsd,\n estSubtotalFromAmount,\n estSubtotalFromAmountBaseUnit,\n estSubtotalUsd,\n estTotalFromAmount: fromAmountString,\n estTotalFromAmountBaseUnit: fromAmountBaseUnitString,\n estTotalUsd,\n finalToAmountBaseUnit: relayQuote.details.currencyOut.amount ?? '0', // TODO: Or do we want 'minimumAmount'?\n fromTokenAddress,\n lpFeePercentage: 0, // TODO: ?\n lpFeeUsd: totalLpFeesUsd,\n metadata: {\n fromAmountBaseUnit:\n params.tradeType === 'EXACT_INPUT'\n ? tokenAmountBaseUnit.toString()\n : (relayQuote.details.currencyIn.amount ?? '0'),\n relayQuote,\n toAmountBaseUnit:\n params.tradeType === 'EXACT_INPUT'\n ? (relayQuote.details.currencyOut.amount ?? '0')\n : tokenAmountBaseUnit.toString(),\n },\n }\n } catch (err) {\n throw new Error(\n `An error occurred trying to generate a relay quote: ${\n err instanceof Error ? err.message : JSON.stringify(err)\n }`,\n )\n }\n}\n", "import type { Address } from 'viem'\nimport {\n FUNKIT_NATIVE_TOKEN,\n RELAY_NATIVE_TOKEN,\n RELAY_TERMINAL_STATUSES,\n} from './constants'\nimport {\n CheckoutRefundState,\n CheckoutState,\n type RelayExecutionInfo,\n} from './types'\n\n/**\n * Converts a token address within Funkit the corresponding Relay token address.\n */\nexport function convertFunToRelayTokenAddress(address: Address): Address {\n if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {\n return RELAY_NATIVE_TOKEN\n }\n\n return address\n}\n\nexport function getRelayExecutionRefundState(\n info: RelayExecutionInfo,\n): CheckoutRefundState | undefined {\n switch (info.status) {\n case 'refund':\n return CheckoutRefundState.REFUNDED\n default:\n return undefined\n }\n}\n\nexport function getRelayExecutionState(\n info: RelayExecutionInfo,\n): CheckoutState {\n switch (info.status) {\n case 'success':\n return CheckoutState.COMPLETED\n case 'failure':\n case 'refund':\n return CheckoutState.CHECKOUT_ERROR\n default:\n return CheckoutState.PENDING_RECEIVAL\n }\n}\n\n/**\n * Checks whether the Relay execution has reached a terminal status.\n */\nexport function isRelayExecutionTerminalStatus(\n info: RelayExecutionInfo,\n): boolean {\n return RELAY_TERMINAL_STATUSES.includes(info.status)\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_relay_sdk", "import_relay_sdk", "import_relay_sdk"]
3
+ "sources": ["../index.ts", "../src/client.ts", "../src/types.ts", "../src/constants.ts", "../src/execution.ts", "../src/fees.ts", "../src/price.ts", "../src/quote.ts", "../src/currency.ts", "../src/utils.ts"],
4
+ "sourcesContent": ["export {\n getRelayClient,\n initializeRelayClient,\n type InitializeRelayClientParams,\n} from './src/client'\nexport {\n FUN_RELAY_REFERRER,\n FUN_RELAY_REVENUE_WALLET,\n RELAY_TERMINAL_STATUSES,\n} from './src/constants'\nexport {\n type ExecuteRelayQuoteParams,\n executeRelayQuote,\n getRelayExecutionInfo,\n} from './src/execution'\nexport { parseRelayFees } from './src/fees'\nexport { getRelayAssetPriceInfo } from './src/price'\nexport {\n type GetRelayQuoteParams,\n getRelayQuote,\n type RelayQuote,\n} from './src/quote'\nexport {\n getRelayExecutionRefundState,\n getRelayExecutionState,\n isRelayExecutionTerminalStatus,\n convertFunToRelayTokenAddress,\n} from './src/utils'\nexport {\n LogLevel,\n type RelayExecutionInfo,\n type RelayExecutionStatus,\n type RelayTokenPriceInfo,\n} from './src/types'\n", "import {\n MAINNET_RELAY_API,\n type RelayClient,\n type RelayClientOptions,\n convertViemChainToRelayChain,\n createClient,\n getClient,\n} from '@reservoir0x/relay-sdk'\nimport type { Chain } from 'viem'\nimport type { Logger } from './types'\n\nexport type InitializeRelayClientParams = Omit<\n RelayClientOptions,\n 'baseApiUrl' | 'chains' | 'logger'\n> & {\n chains: Chain[]\n logger: Logger\n}\n\n/**\n * Initializes a global instance of the RelayClient\n * https://docs.relay.link/references/sdk/createClient\n */\nexport function initializeRelayClient({\n chains,\n logger,\n ...options\n}: InitializeRelayClientParams): RelayClient {\n return createClient({\n ...options,\n baseApiUrl: MAINNET_RELAY_API,\n chains: chains.map(convertViemChainToRelayChain),\n logger: (message) => {\n logger.info('[RelayClient]:', message)\n },\n })\n}\n\n/**\n * Gets the global instance of the RelayClient\n */\nexport function getRelayClient(): RelayClient {\n const client = getClient()\n\n if (!client) {\n throw new Error('Relay client is not defined')\n }\n\n return client\n}\n", "import { LogLevel } from '@reservoir0x/relay-sdk'\nimport type { Abi, Address } from 'viem'\n\nexport { LogLevel }\n\n// https://docs.relay.link/references/api/get-intents-status-v2\nexport interface RelayExecutionInfo {\n status: RelayExecutionStatus\n details: string\n /** Incoming transaction hashes */\n inTxHashes: string[]\n /** Outgoing transaction hashes */\n txHashes: string[]\n /** The last timestamp the data was updated in milliseconds */\n time: number\n originChainId: number\n destinationChainId: number\n}\n\n// https://docs.relay.link/references/api/get-token-price\nexport interface RelayTokenPriceInfo {\n price: number\n}\n\n//// The types below are duplicated from @funkit/api-base atm, but this package should be used in BE as well\n//// TODO: Are we fine with BE importing @funkit/api-base and (by extension) @funkit/utils?\n//// See https://linear.app/funxyz/issue/PE-1342/sdk-extract-domainsrelayts-to-a-new-package#comment-d487d533\n\nexport interface Logger {\n error(message: string, data?: object): void\n info(message: string, data?: object): void\n}\n\n// Reference: https://github.com/reservoirprotocol/relay-kit/blob/211c645f9702a3b459ff545aa4e2e9d536c38455/packages/sdk/src/types/Execute.ts#L54-L61\nexport enum RelayExecutionStatus {\n DELAYED = 'delayed',\n FAILURE = 'failure',\n PENDING = 'pending',\n REFUND = 'refund',\n SUCCESS = 'success',\n WAITING = 'waiting',\n UNKNOWN = 'unknown',\n}\n\nexport interface ApiFunkitCheckoutActionParams {\n contractAbi: Abi\n contractAddress: Address\n functionName: string\n functionArgs: unknown[]\n value?: bigint\n}\n\nexport enum CheckoutRefundState {\n INITIATED = 'INITIATED',\n ERROR = 'ERROR',\n REFUNDED = 'REFUNDED',\n PROCEEDED = 'PROCEEDED',\n WAITING_FOR_FULFILLMENT = 'WAITING_FOR_FULFILLMENT',\n FULFILLED = 'FULFILLED',\n}\n\n// Reference from api server: https://github.com/fun-xyz/fun-api-server/blob/main/src/tables/FunWalletCheckout.ts#L11C1-L21C2\nexport enum CheckoutState {\n // In-progress States\n FROM_UNFUNDED = 'FROM_UNFUNDED',\n FROM_FUNDED = 'FROM_FUNDED',\n FROM_POOLED = 'FROM_POOLED',\n TO_UNFUNDED = 'TO_UNFUNDED',\n TO_FUNDED = 'TO_FUNDED',\n TO_POOLED = 'TO_POOLED',\n TO_READY = 'TO_READY',\n PENDING_RECEIVAL = 'PENDING_RECEIVAL',\n // Terminal States\n COMPLETED = 'COMPLETED',\n CHECKOUT_ERROR = 'CHECKOUT_ERROR',\n EXPIRED = 'EXPIRED',\n CANCELLED = 'CANCELLED',\n}\n\n// The response of the actual /checkout/quote api\nexport type CheckoutApiQuoteResponse = {\n quoteId: string\n estTotalFromAmountBaseUnit: string\n estSubtotalFromAmountBaseUnit: string\n estFeesFromAmountBaseUnit: string\n fromTokenAddress: Address\n estFeesUsd: number\n estSubtotalUsd: number\n estTotalUsd: number\n estCheckoutTimeMs: number\n estMarketMakerGasUsd: number\n lpFeePercentage: number\n lpFeeUsd: number\n}\n\n// The formatted response quote interface from the core sdk\nexport type CheckoutQuoteResponse = CheckoutApiQuoteResponse & {\n estTotalFromAmount: string\n estSubtotalFromAmount: string\n estFeesFromAmount: string\n\n // Any additional fields purely for frontend use\n metadata?: { [key: string]: unknown }\n}\n", "import type { Address } from 'viem'\nimport { RelayExecutionStatus } from './types'\n\n/**\n * Fake address for a chain's native currency used by Funkit\n */\nexport const FUNKIT_NATIVE_TOKEN =\n '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' satisfies Address\n\n/**\n * Fake address for a chain's native currency used by Relay\n */\nexport const RELAY_NATIVE_TOKEN =\n '0x0000000000000000000000000000000000000000' satisfies Address\n\n/**\n * Wallet that receives the app fees collected by Relay\n */\nexport const FUN_RELAY_REVENUE_WALLET =\n '0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E' satisfies Address\n\n/**\n * Referred field in Relay quote\n */\nexport const FUN_RELAY_REFERRER = 'funxyz'\n\n/**\n * Buffer added to Relay's time estimate (which sometimes is 0)\n */\nexport const RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25_000 // 25 seconds\n\nexport const RELAY_TERMINAL_STATUSES: RelayExecutionStatus[] = [\n RelayExecutionStatus.REFUND,\n RelayExecutionStatus.FAILURE,\n RelayExecutionStatus.SUCCESS,\n]\n", "import {\n type Execute,\n MAINNET_RELAY_API,\n type ProgressData,\n} from '@reservoir0x/relay-sdk'\nimport type { Hex, WalletClient } from 'viem'\nimport { getRelayClient } from './client'\nimport type { Logger, RelayExecutionInfo } from './types'\n\nexport type RelayExecutionStep = ProgressData['currentStep'] & {}\n\nexport interface ExecuteRelayQuoteParams {\n logger: Logger\n onConfirmed: (txHash: Hex) => Promise<void>\n onError: (error: Error) => Promise<void>\n onProgress?: (step: RelayExecutionStep | null) => void\n relayQuote: Execute\n walletClient: WalletClient\n}\n\nexport async function executeRelayQuote({\n logger,\n onConfirmed,\n onError,\n onProgress,\n relayQuote,\n walletClient,\n}: ExecuteRelayQuoteParams) {\n await getRelayClient().actions.execute({\n quote: relayQuote,\n wallet: walletClient,\n onProgress: async ({\n steps,\n fees,\n breakdown,\n currentStep,\n currentStepItem,\n txHashes,\n details,\n error,\n }) => {\n const logPrefix = 'onRelayProgress'\n logger.info(`${logPrefix}:params`, {\n steps,\n currentStep,\n fees,\n breakdown,\n currentStepItem,\n txHashes,\n details,\n error,\n })\n\n onProgress?.(currentStep ?? null)\n\n if (error) {\n logger.info(`${logPrefix}:errorDetected`, error)\n await onError(error).catch((e) => {\n logger.error(`${logPrefix}:onErrorFailed`, e)\n })\n } else if (\n // We can redirect as soon as all the required user steps are done\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1748381169792379\n txHashes &&\n txHashes.length > 0 &&\n txHashes.length === steps.length\n ) {\n logger.info(`${logPrefix}:completed`, txHashes)\n // Can we assume its completed here?\n // Use first txHash as the main txHash in fun DE table\n await onConfirmed(txHashes[0].txHash as Hex).catch((e) => {\n logger.error(`${logPrefix}:onConfirmedFailed`, e)\n })\n }\n },\n })\n}\n\nexport async function getRelayExecutionInfo(\n requestId: string,\n): Promise<RelayExecutionInfo> {\n const url = `${MAINNET_RELAY_API}/intents/status/v2?requestId=${requestId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayExecutionInfo\n}\n", "import type { CallFees } from '@reservoir0x/relay-sdk'\nimport type { Logger } from './types'\n\nexport interface FunRelayFeeItem {\n b: number\n v: number\n}\n\nexport async function getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue,\n clientId,\n}: {\n fromTokenAddress: string\n fromChainId: string\n toTokenAddress: string\n toChainId: string\n estUsdValue: number\n clientId: string\n}): Promise<FunRelayFeeItem> {\n const url = `https://frog.fun.xyz/api/fee?fromTokenAddress=${fromTokenAddress}&fromChainId=${fromChainId}&toTokenAddress=${toTokenAddress}&toChainId=${toChainId}&estUsdValue=${estUsdValue}&clientId=${clientId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data\n}\n\nexport function parseRelayFees({\n fees,\n logger,\n}: {\n fees: CallFees | undefined\n logger: Logger\n}) {\n // Gas fees, denominated in source chain native token\n const relayGasFeesUsd = Number.parseFloat(fees?.gas?.amountUsd || '0')\n\n // App fees, denominated in source chain token\n const funLpFeesUsd = Number.parseFloat(fees?.app?.amountUsd || '0')\n const funLpFeesFromAmount = Number.parseFloat(\n fees?.app?.amountFormatted || '0',\n )\n const funLpFeesFromAmountBaseUnit = BigInt(fees?.app?.amount || '0')\n\n // Relay fees, denominated in source chain token\n const relayLpFeesUsd =\n Number.parseFloat(fees?.relayer?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerGas?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerService?.amountUsd || '0')\n const relayLpFeesFromAmount =\n Number.parseFloat(fees?.relayer?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerGas?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerService?.amountFormatted || '0')\n const relayLpFeesFromAmountBaseUnit =\n BigInt(fees?.relayer?.amount || '0') +\n BigInt(fees?.relayerGas?.amount || '0') +\n BigInt(fees?.relayerService?.amount || '0')\n\n const totalLpFeesUsd = funLpFeesUsd + relayLpFeesUsd\n const totalLpFeesFromAmount = funLpFeesFromAmount + relayLpFeesFromAmount\n const totalLpFeesFromAmountBaseUnit =\n funLpFeesFromAmountBaseUnit + relayLpFeesFromAmountBaseUnit\n\n logger.info('parseRelayFees', {\n relayGasFeesUsd,\n funLpFeesUsd,\n funLpFeesFromAmount,\n funLpFeesFromAmountBaseUnit,\n relayLpFeesUsd,\n relayLpFeesFromAmount,\n relayLpFeesFromAmountBaseUnit,\n totalLpFeesUsd,\n totalLpFeesFromAmount,\n totalLpFeesFromAmountBaseUnit,\n })\n\n return {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd: relayGasFeesUsd + totalLpFeesUsd,\n totalFeesFromAmount: totalLpFeesFromAmount,\n totalFeesFromAmountBaseUnit: totalLpFeesFromAmountBaseUnit,\n }\n}\n", "import { MAINNET_RELAY_API } from '@reservoir0x/relay-sdk'\nimport type { RelayTokenPriceInfo } from './types'\n\nexport async function getRelayAssetPriceInfo({\n chainId,\n address,\n}: {\n chainId: string\n address: string\n}): Promise<RelayTokenPriceInfo> {\n const url = `${MAINNET_RELAY_API}/currencies/token/price?chainId=${chainId}&address=${address}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayTokenPriceInfo\n}\n", "import type { Execute, GetQuoteParameters } from '@reservoir0x/relay-sdk'\nimport { type Address, encodeFunctionData } from 'viem'\nimport { getRelayClient } from './client'\nimport {\n FUN_RELAY_REFERRER,\n FUN_RELAY_REVENUE_WALLET,\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n} from './constants'\nimport { getRelayAssetInfo } from './currency'\nimport { getFunRelayFees, parseRelayFees } from './fees'\nimport { getRelayAssetPriceInfo } from './price'\nimport type {\n ApiFunkitCheckoutActionParams,\n CheckoutQuoteResponse,\n Logger,\n} from './types'\nimport { convertFunToRelayTokenAddress } from './utils'\n\ntype RelayQuoteOptions = GetQuoteParameters['options'] & {}\n\nexport type GetRelayQuoteParams = {\n actionParams?: ApiFunkitCheckoutActionParams[]\n fromChainId: string\n fromTokenAddress: Address\n logger: Logger\n /**\n * {@link getRelayQuote} already sets {@link RelayQuoteOptions.appFees|appFees} and {@link RelayQuoteOptions.referrer|referrer}.\n * Only include them if you wish to override.\n */\n options?: RelayQuoteOptions\n recipientAddress: Address | undefined\n toChainId: string\n toTokenAddress: Address\n tradeType: 'EXACT_INPUT' | 'EXACT_OUTPUT'\n userAddress: Address | undefined\n clientId: string\n} & (\n | {\n fromTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_INPUT'\n }\n | {\n toTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_OUTPUT'\n }\n)\n\nexport type RelayQuote = CheckoutQuoteResponse & {\n /** Required for EXACT_INPUT checkouts */\n finalToAmountBaseUnit: string\n metadata: {\n fromAmountBaseUnit: string\n relayQuote: Execute\n toAmountBaseUnit: string\n }\n}\n\nasync function getQuoteEstUsdValue({\n tokenChainId,\n tokenAddress,\n tokenAmountBaseUnit,\n logger,\n}: {\n tokenChainId: string\n tokenAddress: string\n tokenAmountBaseUnit: string\n logger: Logger\n}) {\n try {\n const [tokenPriceRes, tokenInfoRes] = await Promise.all([\n getRelayAssetPriceInfo({\n chainId: tokenChainId,\n address: convertFunToRelayTokenAddress(tokenAddress as Address),\n }),\n getRelayAssetInfo({\n chainId: tokenChainId,\n address: convertFunToRelayTokenAddress(tokenAddress as Address),\n }),\n ])\n\n const price = tokenPriceRes.price\n const decimals = tokenInfoRes.decimals\n\n const absoluteAmount = BigInt(tokenAmountBaseUnit) / BigInt(10 ** decimals)\n return Number(price) * Number(absoluteAmount)\n } catch (err) {\n logger.error('getQuoteEstUsdValueError', {\n message: `Failed to get USD value for token ${tokenAddress} on chain ${tokenChainId}: ${\n err instanceof Error ? err.message : JSON.stringify(err)\n }. Falling back to 0 USD.`,\n })\n // If any part fails, just fallback to 0 USD so that we do not block quote\n return 0\n }\n}\n\nexport async function getRelayQuote({\n logger,\n ...params\n}: GetRelayQuoteParams): Promise<RelayQuote> {\n const {\n actionParams,\n fromChainId,\n fromTokenAddress,\n options,\n recipientAddress,\n toChainId,\n toTokenAddress,\n userAddress,\n clientId,\n } = params\n\n try {\n const relayClient = getRelayClient()\n\n const txs = actionParams?.map((action) => {\n const data = encodeFunctionData({\n abi: action.contractAbi,\n args: action.functionArgs,\n functionName: action.functionName,\n })\n\n return {\n data,\n to: action.contractAddress,\n value: String(action.value ?? 0n),\n }\n })\n\n const isExactIn = params.tradeType === 'EXACT_INPUT'\n const queryTokenAmountBaseUnit = isExactIn\n ? params.fromTokenAmountBaseUnit\n : params.toTokenAmountBaseUnit\n const queryTokenAddress = isExactIn ? fromTokenAddress : toTokenAddress\n const queryTokenChainId = isExactIn ? fromChainId : toChainId\n\n const estUsdValue = await getQuoteEstUsdValue({\n tokenChainId: queryTokenChainId,\n tokenAddress: queryTokenAddress,\n tokenAmountBaseUnit: queryTokenAmountBaseUnit.toString(),\n logger,\n })\n\n const feeInfo = await getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue: Number(estUsdValue) || 0,\n clientId,\n })\n\n const appFeeBp = feeInfo.b + feeInfo.v\n\n logger.info('getRelayQuoteParams', {\n ...params,\n queryTokenAmountBaseUnit,\n txs,\n estUsdValue,\n feeInfo,\n appFeeBp,\n })\n\n // Get the full quote with fees\n const relayQuote = await relayClient.actions.getQuote({\n chainId: Number(fromChainId),\n toChainId: Number(toChainId),\n currency: convertFunToRelayTokenAddress(fromTokenAddress),\n toCurrency: convertFunToRelayTokenAddress(toTokenAddress),\n amount: queryTokenAmountBaseUnit.toString(),\n recipient: recipientAddress,\n tradeType: params.tradeType,\n user: userAddress,\n ...(txs && { txs }),\n options: {\n referrer: clientId\n ? `${FUN_RELAY_REFERRER}|${clientId}`\n : FUN_RELAY_REFERRER,\n appFees: [\n {\n fee: appFeeBp.toString(),\n recipient: FUN_RELAY_REVENUE_WALLET,\n },\n ],\n ...options,\n },\n })\n\n logger.info('relayQuote', relayQuote)\n\n const estSubtotalUsd = Number(\n relayQuote.details?.currencyOut?.amountUsd || 0,\n )\n const estTotalUsd = Number(relayQuote.details?.currencyIn?.amountUsd || 0)\n // Get how much fromAmount is needed for the quote\n const fromAmountString =\n relayQuote.details?.currencyIn?.amountFormatted || '0'\n const fromAmountBaseUnitString =\n relayQuote.details?.currencyIn?.amount || '0'\n\n // RequestID will be consistent across steps in the quote\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1747774944603209\n const relayRequestId = relayQuote.steps[0]?.requestId\n\n // TODO: Verify with relay team if this is possible?\n if (!relayRequestId) {\n throw new Error('Relay quote does not contain a requestId')\n }\n\n // TODO: Verify with relay team if this is possible?\n if (!relayQuote.details?.currencyIn || !relayQuote.details?.currencyOut) {\n throw new Error('Relay quote does not contain trade details')\n }\n\n const {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd,\n totalFeesFromAmount,\n totalFeesFromAmountBaseUnit,\n } = parseRelayFees({ fees: relayQuote.fees, logger })\n\n const estSubtotalFromAmount = (\n Number.parseFloat(fromAmountString) - totalFeesFromAmount\n ).toString()\n\n const estSubtotalFromAmountBaseUnit = (\n BigInt(fromAmountBaseUnitString) - totalFeesFromAmountBaseUnit\n ).toString()\n\n return {\n quoteId: relayRequestId,\n estCheckoutTimeMs:\n (relayQuote.details.timeEstimate || 0) * 1000 +\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n estFeesFromAmount: totalFeesFromAmount.toString(),\n estFeesFromAmountBaseUnit: totalFeesFromAmountBaseUnit.toString(),\n estFeesUsd: totalFeesUsd,\n estMarketMakerGasUsd: relayGasFeesUsd,\n estSubtotalFromAmount,\n estSubtotalFromAmountBaseUnit,\n estSubtotalUsd,\n estTotalFromAmount: fromAmountString,\n estTotalFromAmountBaseUnit: fromAmountBaseUnitString,\n estTotalUsd,\n finalToAmountBaseUnit: relayQuote.details.currencyOut.amount ?? '0', // TODO: Or do we want 'minimumAmount'?\n fromTokenAddress,\n lpFeePercentage: 0, // TODO: ?\n lpFeeUsd: totalLpFeesUsd,\n metadata: {\n fromAmountBaseUnit: isExactIn\n ? queryTokenAmountBaseUnit.toString()\n : (relayQuote.details.currencyIn.amount ?? '0'),\n relayQuote,\n toAmountBaseUnit: isExactIn\n ? (relayQuote.details.currencyOut.amount ?? '0')\n : queryTokenAmountBaseUnit.toString(),\n },\n }\n } catch (err) {\n throw new Error(\n `An error occurred trying to generate a relay quote: ${\n err instanceof Error ? err.message : JSON.stringify(err)\n }`,\n )\n }\n}\n", "import { MAINNET_RELAY_API } from '@reservoir0x/relay-sdk'\n\nexport interface RelayTokenInfo {\n chainId: number\n address: string\n symbol: string\n name: string\n decimals: number\n vmType: string\n metadata: {\n logoURI: string\n verified: boolean\n isNative: boolean\n }\n}\n\nexport async function getRelayAssetInfo({\n chainId,\n address,\n}: {\n chainId: string\n address: string\n}): Promise<RelayTokenInfo> {\n const url = `${MAINNET_RELAY_API}/currencies/v2`\n const body = {\n chainIds: [chainId],\n address,\n }\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data?.[0] as RelayTokenInfo\n}\n", "import type { Address } from 'viem'\nimport {\n FUNKIT_NATIVE_TOKEN,\n RELAY_NATIVE_TOKEN,\n RELAY_TERMINAL_STATUSES,\n} from './constants'\nimport {\n CheckoutRefundState,\n CheckoutState,\n type RelayExecutionInfo,\n} from './types'\n\n/**\n * Converts a token address within Funkit the corresponding Relay token address.\n */\nexport function convertFunToRelayTokenAddress(address: Address): Address {\n if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {\n return RELAY_NATIVE_TOKEN\n }\n\n return address\n}\n\nexport function getRelayExecutionRefundState(\n info: RelayExecutionInfo,\n): CheckoutRefundState | undefined {\n switch (info.status) {\n case 'refund':\n return CheckoutRefundState.REFUNDED\n default:\n return undefined\n }\n}\n\nexport function getRelayExecutionState(\n info: RelayExecutionInfo,\n): CheckoutState {\n switch (info.status) {\n case 'success':\n return CheckoutState.COMPLETED\n case 'failure':\n case 'refund':\n return CheckoutState.CHECKOUT_ERROR\n default:\n return CheckoutState.PENDING_RECEIVAL\n }\n}\n\n/**\n * Checks whether the Relay execution has reached a terminal status.\n */\nexport function isRelayExecutionTerminalStatus(\n info: RelayExecutionInfo,\n): boolean {\n return RELAY_TERMINAL_STATUSES.includes(info.status)\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_relay_sdk", "import_relay_sdk", "import_relay_sdk", "import_relay_sdk"]
7
7
  }
package/dist/index.mjs CHANGED
@@ -179,6 +179,29 @@ async function getRelayAssetPriceInfo({
179
179
  // src/quote.ts
180
180
  import { encodeFunctionData } from "viem";
181
181
 
182
+ // src/currency.ts
183
+ import { MAINNET_RELAY_API as MAINNET_RELAY_API4 } from "@reservoir0x/relay-sdk";
184
+ async function getRelayAssetInfo({
185
+ chainId,
186
+ address
187
+ }) {
188
+ const url = `${MAINNET_RELAY_API4}/currencies/v2`;
189
+ const body = {
190
+ chainIds: [chainId],
191
+ address
192
+ };
193
+ const response = await fetch(url, {
194
+ method: "POST",
195
+ headers: { "Content-Type": "application/json" },
196
+ body: JSON.stringify(body)
197
+ });
198
+ if (!response.ok) {
199
+ throw Error(response.statusText);
200
+ }
201
+ const data = await response.json();
202
+ return data?.[0];
203
+ }
204
+
182
205
  // src/utils.ts
183
206
  function convertFunToRelayTokenAddress(address) {
184
207
  if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {
@@ -210,6 +233,34 @@ function isRelayExecutionTerminalStatus(info) {
210
233
  }
211
234
 
212
235
  // src/quote.ts
236
+ async function getQuoteEstUsdValue({
237
+ tokenChainId,
238
+ tokenAddress,
239
+ tokenAmountBaseUnit,
240
+ logger
241
+ }) {
242
+ try {
243
+ const [tokenPriceRes, tokenInfoRes] = await Promise.all([
244
+ getRelayAssetPriceInfo({
245
+ chainId: tokenChainId,
246
+ address: convertFunToRelayTokenAddress(tokenAddress)
247
+ }),
248
+ getRelayAssetInfo({
249
+ chainId: tokenChainId,
250
+ address: convertFunToRelayTokenAddress(tokenAddress)
251
+ })
252
+ ]);
253
+ const price = tokenPriceRes.price;
254
+ const decimals = tokenInfoRes.decimals;
255
+ const absoluteAmount = BigInt(tokenAmountBaseUnit) / BigInt(10 ** decimals);
256
+ return Number(price) * Number(absoluteAmount);
257
+ } catch (err) {
258
+ logger.error("getQuoteEstUsdValueError", {
259
+ message: `Failed to get USD value for token ${tokenAddress} on chain ${tokenChainId}: ${err instanceof Error ? err.message : JSON.stringify(err)}. Falling back to 0 USD.`
260
+ });
261
+ return 0;
262
+ }
263
+ }
213
264
  async function getRelayQuote({
214
265
  logger,
215
266
  ...params
@@ -227,8 +278,6 @@ async function getRelayQuote({
227
278
  } = params;
228
279
  try {
229
280
  const relayClient = getRelayClient();
230
- const isExactIn = params.tradeType === "EXACT_INPUT";
231
- const tokenAmountBaseUnit = isExactIn ? params.fromTokenAmountBaseUnit : params.toTokenAmountBaseUnit;
232
281
  const txs = actionParams?.map((action) => {
233
282
  const data = encodeFunctionData({
234
283
  abi: action.contractAbi,
@@ -241,18 +290,16 @@ async function getRelayQuote({
241
290
  value: String(action.value ?? 0n)
242
291
  };
243
292
  });
244
- const priceInfo = await relayClient.actions.getPrice({
245
- originChainId: Number(fromChainId),
246
- originCurrency: convertFunToRelayTokenAddress(fromTokenAddress),
247
- destinationChainId: Number(toChainId),
248
- destinationCurrency: convertFunToRelayTokenAddress(toTokenAddress),
249
- amount: tokenAmountBaseUnit.toString(),
250
- tradeType: params.tradeType,
251
- user: userAddress,
252
- recipient: recipientAddress,
253
- options
293
+ const isExactIn = params.tradeType === "EXACT_INPUT";
294
+ const queryTokenAmountBaseUnit = isExactIn ? params.fromTokenAmountBaseUnit : params.toTokenAmountBaseUnit;
295
+ const queryTokenAddress = isExactIn ? fromTokenAddress : toTokenAddress;
296
+ const queryTokenChainId = isExactIn ? fromChainId : toChainId;
297
+ const estUsdValue = await getQuoteEstUsdValue({
298
+ tokenChainId: queryTokenChainId,
299
+ tokenAddress: queryTokenAddress,
300
+ tokenAmountBaseUnit: queryTokenAmountBaseUnit.toString(),
301
+ logger
254
302
  });
255
- const estUsdValue = priceInfo.details?.currencyIn?.amountUsd;
256
303
  const feeInfo = await getFunRelayFees({
257
304
  fromTokenAddress,
258
305
  fromChainId,
@@ -264,9 +311,9 @@ async function getRelayQuote({
264
311
  const appFeeBp = feeInfo.b + feeInfo.v;
265
312
  logger.info("getRelayQuoteParams", {
266
313
  ...params,
267
- tokenAmountBaseUnit,
314
+ queryTokenAmountBaseUnit,
268
315
  txs,
269
- priceInfo,
316
+ estUsdValue,
270
317
  feeInfo,
271
318
  appFeeBp
272
319
  });
@@ -275,7 +322,7 @@ async function getRelayQuote({
275
322
  toChainId: Number(toChainId),
276
323
  currency: convertFunToRelayTokenAddress(fromTokenAddress),
277
324
  toCurrency: convertFunToRelayTokenAddress(toTokenAddress),
278
- amount: tokenAmountBaseUnit.toString(),
325
+ amount: queryTokenAmountBaseUnit.toString(),
279
326
  recipient: recipientAddress,
280
327
  tradeType: params.tradeType,
281
328
  user: userAddress,
@@ -334,9 +381,9 @@ async function getRelayQuote({
334
381
  // TODO: ?
335
382
  lpFeeUsd: totalLpFeesUsd,
336
383
  metadata: {
337
- fromAmountBaseUnit: params.tradeType === "EXACT_INPUT" ? tokenAmountBaseUnit.toString() : relayQuote.details.currencyIn.amount ?? "0",
384
+ fromAmountBaseUnit: isExactIn ? queryTokenAmountBaseUnit.toString() : relayQuote.details.currencyIn.amount ?? "0",
338
385
  relayQuote,
339
- toAmountBaseUnit: params.tradeType === "EXACT_INPUT" ? relayQuote.details.currencyOut.amount ?? "0" : tokenAmountBaseUnit.toString()
386
+ toAmountBaseUnit: isExactIn ? relayQuote.details.currencyOut.amount ?? "0" : queryTokenAmountBaseUnit.toString()
340
387
  }
341
388
  };
342
389
  } catch (err) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/client.ts", "../src/types.ts", "../src/constants.ts", "../src/execution.ts", "../src/fees.ts", "../src/price.ts", "../src/quote.ts", "../src/utils.ts"],
4
- "sourcesContent": ["import {\n MAINNET_RELAY_API,\n type RelayClient,\n type RelayClientOptions,\n convertViemChainToRelayChain,\n createClient,\n getClient,\n} from '@reservoir0x/relay-sdk'\nimport type { Chain } from 'viem'\nimport type { Logger } from './types'\n\nexport type InitializeRelayClientParams = Omit<\n RelayClientOptions,\n 'baseApiUrl' | 'chains' | 'logger'\n> & {\n chains: Chain[]\n logger: Logger\n}\n\n/**\n * Initializes a global instance of the RelayClient\n * https://docs.relay.link/references/sdk/createClient\n */\nexport function initializeRelayClient({\n chains,\n logger,\n ...options\n}: InitializeRelayClientParams): RelayClient {\n return createClient({\n ...options,\n baseApiUrl: MAINNET_RELAY_API,\n chains: chains.map(convertViemChainToRelayChain),\n logger: (message) => {\n logger.info('[RelayClient]:', message)\n },\n })\n}\n\n/**\n * Gets the global instance of the RelayClient\n */\nexport function getRelayClient(): RelayClient {\n const client = getClient()\n\n if (!client) {\n throw new Error('Relay client is not defined')\n }\n\n return client\n}\n", "import { LogLevel } from '@reservoir0x/relay-sdk'\nimport type { Abi, Address } from 'viem'\n\nexport { LogLevel }\n\n// https://docs.relay.link/references/api/get-intents-status-v2\nexport interface RelayExecutionInfo {\n status: RelayExecutionStatus\n details: string\n /** Incoming transaction hashes */\n inTxHashes: string[]\n /** Outgoing transaction hashes */\n txHashes: string[]\n /** The last timestamp the data was updated in milliseconds */\n time: number\n originChainId: number\n destinationChainId: number\n}\n\n// https://docs.relay.link/references/api/get-token-price\nexport interface RelayTokenPriceInfo {\n price: number\n}\n\n//// The types below are duplicated from @funkit/api-base atm, but this package should be used in BE as well\n//// TODO: Are we fine with BE importing @funkit/api-base and (by extension) @funkit/utils?\n//// See https://linear.app/funxyz/issue/PE-1342/sdk-extract-domainsrelayts-to-a-new-package#comment-d487d533\n\nexport interface Logger {\n error(message: string, data?: object): void\n info(message: string, data?: object): void\n}\n\n// Reference: https://github.com/reservoirprotocol/relay-kit/blob/211c645f9702a3b459ff545aa4e2e9d536c38455/packages/sdk/src/types/Execute.ts#L54-L61\nexport enum RelayExecutionStatus {\n DELAYED = 'delayed',\n FAILURE = 'failure',\n PENDING = 'pending',\n REFUND = 'refund',\n SUCCESS = 'success',\n WAITING = 'waiting',\n UNKNOWN = 'unknown',\n}\n\nexport interface ApiFunkitCheckoutActionParams {\n contractAbi: Abi\n contractAddress: Address\n functionName: string\n functionArgs: unknown[]\n value?: bigint\n}\n\nexport enum CheckoutRefundState {\n INITIATED = 'INITIATED',\n ERROR = 'ERROR',\n REFUNDED = 'REFUNDED',\n PROCEEDED = 'PROCEEDED',\n WAITING_FOR_FULFILLMENT = 'WAITING_FOR_FULFILLMENT',\n FULFILLED = 'FULFILLED',\n}\n\n// Reference from api server: https://github.com/fun-xyz/fun-api-server/blob/main/src/tables/FunWalletCheckout.ts#L11C1-L21C2\nexport enum CheckoutState {\n // In-progress States\n FROM_UNFUNDED = 'FROM_UNFUNDED',\n FROM_FUNDED = 'FROM_FUNDED',\n FROM_POOLED = 'FROM_POOLED',\n TO_UNFUNDED = 'TO_UNFUNDED',\n TO_FUNDED = 'TO_FUNDED',\n TO_POOLED = 'TO_POOLED',\n TO_READY = 'TO_READY',\n PENDING_RECEIVAL = 'PENDING_RECEIVAL',\n // Terminal States\n COMPLETED = 'COMPLETED',\n CHECKOUT_ERROR = 'CHECKOUT_ERROR',\n EXPIRED = 'EXPIRED',\n CANCELLED = 'CANCELLED',\n}\n\n// The response of the actual /checkout/quote api\nexport type CheckoutApiQuoteResponse = {\n quoteId: string\n estTotalFromAmountBaseUnit: string\n estSubtotalFromAmountBaseUnit: string\n estFeesFromAmountBaseUnit: string\n fromTokenAddress: Address\n estFeesUsd: number\n estSubtotalUsd: number\n estTotalUsd: number\n estCheckoutTimeMs: number\n estMarketMakerGasUsd: number\n lpFeePercentage: number\n lpFeeUsd: number\n}\n\n// The formatted response quote interface from the core sdk\nexport type CheckoutQuoteResponse = CheckoutApiQuoteResponse & {\n estTotalFromAmount: string\n estSubtotalFromAmount: string\n estFeesFromAmount: string\n\n // Any additional fields purely for frontend use\n metadata?: { [key: string]: unknown }\n}\n", "import type { Address } from 'viem'\nimport { RelayExecutionStatus } from './types'\n\n/**\n * Fake address for a chain's native currency used by Funkit\n */\nexport const FUNKIT_NATIVE_TOKEN =\n '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' satisfies Address\n\n/**\n * Fake address for a chain's native currency used by Relay\n */\nexport const RELAY_NATIVE_TOKEN =\n '0x0000000000000000000000000000000000000000' satisfies Address\n\n/**\n * Wallet that receives the app fees collected by Relay\n */\nexport const FUN_RELAY_REVENUE_WALLET =\n '0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E' satisfies Address\n\n/**\n * Referred field in Relay quote\n */\nexport const FUN_RELAY_REFERRER = 'funxyz'\n\n/**\n * Buffer added to Relay's time estimate (which sometimes is 0)\n */\nexport const RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25_000 // 25 seconds\n\nexport const RELAY_TERMINAL_STATUSES: RelayExecutionStatus[] = [\n RelayExecutionStatus.REFUND,\n RelayExecutionStatus.FAILURE,\n RelayExecutionStatus.SUCCESS,\n]\n", "import {\n type Execute,\n MAINNET_RELAY_API,\n type ProgressData,\n} from '@reservoir0x/relay-sdk'\nimport type { Hex, WalletClient } from 'viem'\nimport { getRelayClient } from './client'\nimport type { Logger, RelayExecutionInfo } from './types'\n\nexport type RelayExecutionStep = ProgressData['currentStep'] & {}\n\nexport interface ExecuteRelayQuoteParams {\n logger: Logger\n onConfirmed: (txHash: Hex) => Promise<void>\n onError: (error: Error) => Promise<void>\n onProgress?: (step: RelayExecutionStep | null) => void\n relayQuote: Execute\n walletClient: WalletClient\n}\n\nexport async function executeRelayQuote({\n logger,\n onConfirmed,\n onError,\n onProgress,\n relayQuote,\n walletClient,\n}: ExecuteRelayQuoteParams) {\n await getRelayClient().actions.execute({\n quote: relayQuote,\n wallet: walletClient,\n onProgress: async ({\n steps,\n fees,\n breakdown,\n currentStep,\n currentStepItem,\n txHashes,\n details,\n error,\n }) => {\n const logPrefix = 'onRelayProgress'\n logger.info(`${logPrefix}:params`, {\n steps,\n currentStep,\n fees,\n breakdown,\n currentStepItem,\n txHashes,\n details,\n error,\n })\n\n onProgress?.(currentStep ?? null)\n\n if (error) {\n logger.info(`${logPrefix}:errorDetected`, error)\n await onError(error).catch((e) => {\n logger.error(`${logPrefix}:onErrorFailed`, e)\n })\n } else if (\n // We can redirect as soon as all the required user steps are done\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1748381169792379\n txHashes &&\n txHashes.length > 0 &&\n txHashes.length === steps.length\n ) {\n logger.info(`${logPrefix}:completed`, txHashes)\n // Can we assume its completed here?\n // Use first txHash as the main txHash in fun DE table\n await onConfirmed(txHashes[0].txHash as Hex).catch((e) => {\n logger.error(`${logPrefix}:onConfirmedFailed`, e)\n })\n }\n },\n })\n}\n\nexport async function getRelayExecutionInfo(\n requestId: string,\n): Promise<RelayExecutionInfo> {\n const url = `${MAINNET_RELAY_API}/intents/status/v2?requestId=${requestId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayExecutionInfo\n}\n", "import type { CallFees } from '@reservoir0x/relay-sdk'\nimport type { Logger } from './types'\n\nexport interface FunRelayFeeItem {\n b: number\n v: number\n}\n\nexport async function getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue,\n clientId,\n}: {\n fromTokenAddress: string\n fromChainId: string\n toTokenAddress: string\n toChainId: string\n estUsdValue: number\n clientId: string\n}): Promise<FunRelayFeeItem> {\n const url = `https://frog.fun.xyz/api/fee?fromTokenAddress=${fromTokenAddress}&fromChainId=${fromChainId}&toTokenAddress=${toTokenAddress}&toChainId=${toChainId}&estUsdValue=${estUsdValue}&clientId=${clientId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data\n}\n\nexport function parseRelayFees({\n fees,\n logger,\n}: {\n fees: CallFees | undefined\n logger: Logger\n}) {\n // Gas fees, denominated in source chain native token\n const relayGasFeesUsd = Number.parseFloat(fees?.gas?.amountUsd || '0')\n\n // App fees, denominated in source chain token\n const funLpFeesUsd = Number.parseFloat(fees?.app?.amountUsd || '0')\n const funLpFeesFromAmount = Number.parseFloat(\n fees?.app?.amountFormatted || '0',\n )\n const funLpFeesFromAmountBaseUnit = BigInt(fees?.app?.amount || '0')\n\n // Relay fees, denominated in source chain token\n const relayLpFeesUsd =\n Number.parseFloat(fees?.relayer?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerGas?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerService?.amountUsd || '0')\n const relayLpFeesFromAmount =\n Number.parseFloat(fees?.relayer?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerGas?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerService?.amountFormatted || '0')\n const relayLpFeesFromAmountBaseUnit =\n BigInt(fees?.relayer?.amount || '0') +\n BigInt(fees?.relayerGas?.amount || '0') +\n BigInt(fees?.relayerService?.amount || '0')\n\n const totalLpFeesUsd = funLpFeesUsd + relayLpFeesUsd\n const totalLpFeesFromAmount = funLpFeesFromAmount + relayLpFeesFromAmount\n const totalLpFeesFromAmountBaseUnit =\n funLpFeesFromAmountBaseUnit + relayLpFeesFromAmountBaseUnit\n\n logger.info('parseRelayFees', {\n relayGasFeesUsd,\n funLpFeesUsd,\n funLpFeesFromAmount,\n funLpFeesFromAmountBaseUnit,\n relayLpFeesUsd,\n relayLpFeesFromAmount,\n relayLpFeesFromAmountBaseUnit,\n totalLpFeesUsd,\n totalLpFeesFromAmount,\n totalLpFeesFromAmountBaseUnit,\n })\n\n return {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd: relayGasFeesUsd + totalLpFeesUsd,\n totalFeesFromAmount: totalLpFeesFromAmount,\n totalFeesFromAmountBaseUnit: totalLpFeesFromAmountBaseUnit,\n }\n}\n", "import { MAINNET_RELAY_API } from '@reservoir0x/relay-sdk'\nimport type { RelayTokenPriceInfo } from './types'\n\nexport async function getRelayAssetPriceInfo({\n chainId,\n address,\n}: {\n chainId: string\n address: string\n}): Promise<RelayTokenPriceInfo> {\n const url = `${MAINNET_RELAY_API}/currencies/token/price?chainId=${chainId}&address=${address}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayTokenPriceInfo\n}\n", "import type { Execute, GetQuoteParameters } from '@reservoir0x/relay-sdk'\nimport { type Address, encodeFunctionData } from 'viem'\nimport { getRelayClient } from './client'\nimport {\n FUN_RELAY_REFERRER,\n FUN_RELAY_REVENUE_WALLET,\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n} from './constants'\nimport { getFunRelayFees, parseRelayFees } from './fees'\nimport type {\n ApiFunkitCheckoutActionParams,\n CheckoutQuoteResponse,\n Logger,\n} from './types'\nimport { convertFunToRelayTokenAddress } from './utils'\n\ntype RelayQuoteOptions = GetQuoteParameters['options'] & {}\n\nexport type GetRelayQuoteParams = {\n actionParams?: ApiFunkitCheckoutActionParams[]\n fromChainId: string\n fromTokenAddress: Address\n logger: Logger\n /**\n * {@link getRelayQuote} already sets {@link RelayQuoteOptions.appFees|appFees} and {@link RelayQuoteOptions.referrer|referrer}.\n * Only include them if you wish to override.\n */\n options?: RelayQuoteOptions\n recipientAddress: Address | undefined\n toChainId: string\n toTokenAddress: Address\n tradeType: 'EXACT_INPUT' | 'EXACT_OUTPUT'\n userAddress: Address | undefined\n clientId: string\n} & (\n | {\n fromTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_INPUT'\n }\n | {\n toTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_OUTPUT'\n }\n)\n\nexport type RelayQuote = CheckoutQuoteResponse & {\n /** Required for EXACT_INPUT checkouts */\n finalToAmountBaseUnit: string\n metadata: {\n fromAmountBaseUnit: string\n relayQuote: Execute\n toAmountBaseUnit: string\n }\n}\n\nexport async function getRelayQuote({\n logger,\n ...params\n}: GetRelayQuoteParams): Promise<RelayQuote> {\n const {\n actionParams,\n fromChainId,\n fromTokenAddress,\n options,\n recipientAddress,\n toChainId,\n toTokenAddress,\n userAddress,\n clientId,\n } = params\n\n try {\n const relayClient = getRelayClient()\n\n const isExactIn = params.tradeType === 'EXACT_INPUT'\n const tokenAmountBaseUnit = isExactIn\n ? params.fromTokenAmountBaseUnit\n : params.toTokenAmountBaseUnit\n\n const txs = actionParams?.map((action) => {\n const data = encodeFunctionData({\n abi: action.contractAbi,\n args: action.functionArgs,\n functionName: action.functionName,\n })\n\n return {\n data,\n to: action.contractAddress,\n value: String(action.value ?? 0n),\n }\n })\n\n const priceInfo = await relayClient.actions.getPrice({\n originChainId: Number(fromChainId),\n originCurrency: convertFunToRelayTokenAddress(fromTokenAddress),\n destinationChainId: Number(toChainId),\n destinationCurrency: convertFunToRelayTokenAddress(toTokenAddress),\n amount: tokenAmountBaseUnit.toString(),\n tradeType: params.tradeType,\n user: userAddress,\n recipient: recipientAddress,\n options,\n })\n\n const estUsdValue = priceInfo.details?.currencyIn?.amountUsd\n\n const feeInfo = await getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue: Number(estUsdValue) || 0,\n clientId,\n })\n const appFeeBp = feeInfo.b + feeInfo.v\n\n logger.info('getRelayQuoteParams', {\n ...params,\n tokenAmountBaseUnit,\n txs,\n priceInfo,\n feeInfo,\n appFeeBp,\n })\n\n // Get the relay quote\n const relayQuote = await relayClient.actions.getQuote({\n chainId: Number(fromChainId),\n toChainId: Number(toChainId),\n currency: convertFunToRelayTokenAddress(fromTokenAddress),\n toCurrency: convertFunToRelayTokenAddress(toTokenAddress),\n amount: tokenAmountBaseUnit.toString(),\n recipient: recipientAddress,\n tradeType: params.tradeType,\n user: userAddress,\n ...(txs && { txs }),\n options: {\n referrer: clientId\n ? `${FUN_RELAY_REFERRER}|${clientId}`\n : FUN_RELAY_REFERRER,\n appFees: [\n {\n fee: appFeeBp.toString(),\n recipient: FUN_RELAY_REVENUE_WALLET,\n },\n ],\n ...options,\n },\n })\n\n // TODO: Handling for no route response\n\n logger.info('relayQuote', relayQuote)\n\n const estSubtotalUsd = Number(\n relayQuote.details?.currencyOut?.amountUsd || 0,\n )\n const estTotalUsd = Number(relayQuote.details?.currencyIn?.amountUsd || 0)\n // Get how much fromAmount is needed for the quote\n const fromAmountString =\n relayQuote.details?.currencyIn?.amountFormatted || '0'\n const fromAmountBaseUnitString =\n relayQuote.details?.currencyIn?.amount || '0'\n\n // RequestID will be consistent across steps in the quote\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1747774944603209\n const relayRequestId = relayQuote.steps[0]?.requestId\n\n // TODO: Verify with relay team if this is possible?\n if (!relayRequestId) {\n throw new Error('Relay quote does not contain a requestId')\n }\n\n // TODO: Verify with relay team if this is possible?\n if (!relayQuote.details?.currencyIn || !relayQuote.details?.currencyOut) {\n throw new Error('Relay quote does not contain trade details')\n }\n\n const {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd,\n totalFeesFromAmount,\n totalFeesFromAmountBaseUnit,\n } = parseRelayFees({ fees: relayQuote.fees, logger })\n\n const estSubtotalFromAmount = (\n Number.parseFloat(fromAmountString) - totalFeesFromAmount\n ).toString()\n\n const estSubtotalFromAmountBaseUnit = (\n BigInt(fromAmountBaseUnitString) - totalFeesFromAmountBaseUnit\n ).toString()\n\n return {\n quoteId: relayRequestId,\n estCheckoutTimeMs:\n (relayQuote.details.timeEstimate || 0) * 1000 +\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n estFeesFromAmount: totalFeesFromAmount.toString(),\n estFeesFromAmountBaseUnit: totalFeesFromAmountBaseUnit.toString(),\n estFeesUsd: totalFeesUsd,\n estMarketMakerGasUsd: relayGasFeesUsd,\n estSubtotalFromAmount,\n estSubtotalFromAmountBaseUnit,\n estSubtotalUsd,\n estTotalFromAmount: fromAmountString,\n estTotalFromAmountBaseUnit: fromAmountBaseUnitString,\n estTotalUsd,\n finalToAmountBaseUnit: relayQuote.details.currencyOut.amount ?? '0', // TODO: Or do we want 'minimumAmount'?\n fromTokenAddress,\n lpFeePercentage: 0, // TODO: ?\n lpFeeUsd: totalLpFeesUsd,\n metadata: {\n fromAmountBaseUnit:\n params.tradeType === 'EXACT_INPUT'\n ? tokenAmountBaseUnit.toString()\n : (relayQuote.details.currencyIn.amount ?? '0'),\n relayQuote,\n toAmountBaseUnit:\n params.tradeType === 'EXACT_INPUT'\n ? (relayQuote.details.currencyOut.amount ?? '0')\n : tokenAmountBaseUnit.toString(),\n },\n }\n } catch (err) {\n throw new Error(\n `An error occurred trying to generate a relay quote: ${\n err instanceof Error ? err.message : JSON.stringify(err)\n }`,\n )\n }\n}\n", "import type { Address } from 'viem'\nimport {\n FUNKIT_NATIVE_TOKEN,\n RELAY_NATIVE_TOKEN,\n RELAY_TERMINAL_STATUSES,\n} from './constants'\nimport {\n CheckoutRefundState,\n CheckoutState,\n type RelayExecutionInfo,\n} from './types'\n\n/**\n * Converts a token address within Funkit the corresponding Relay token address.\n */\nexport function convertFunToRelayTokenAddress(address: Address): Address {\n if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {\n return RELAY_NATIVE_TOKEN\n }\n\n return address\n}\n\nexport function getRelayExecutionRefundState(\n info: RelayExecutionInfo,\n): CheckoutRefundState | undefined {\n switch (info.status) {\n case 'refund':\n return CheckoutRefundState.REFUNDED\n default:\n return undefined\n }\n}\n\nexport function getRelayExecutionState(\n info: RelayExecutionInfo,\n): CheckoutState {\n switch (info.status) {\n case 'success':\n return CheckoutState.COMPLETED\n case 'failure':\n case 'refund':\n return CheckoutState.CHECKOUT_ERROR\n default:\n return CheckoutState.PENDING_RECEIVAL\n }\n}\n\n/**\n * Checks whether the Relay execution has reached a terminal status.\n */\nexport function isRelayExecutionTerminalStatus(\n info: RelayExecutionInfo,\n): boolean {\n return RELAY_TERMINAL_STATUSES.includes(info.status)\n}\n"],
5
- "mappings": "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",
6
- "names": ["MAINNET_RELAY_API", "MAINNET_RELAY_API", "MAINNET_RELAY_API"]
3
+ "sources": ["../src/client.ts", "../src/types.ts", "../src/constants.ts", "../src/execution.ts", "../src/fees.ts", "../src/price.ts", "../src/quote.ts", "../src/currency.ts", "../src/utils.ts"],
4
+ "sourcesContent": ["import {\n MAINNET_RELAY_API,\n type RelayClient,\n type RelayClientOptions,\n convertViemChainToRelayChain,\n createClient,\n getClient,\n} from '@reservoir0x/relay-sdk'\nimport type { Chain } from 'viem'\nimport type { Logger } from './types'\n\nexport type InitializeRelayClientParams = Omit<\n RelayClientOptions,\n 'baseApiUrl' | 'chains' | 'logger'\n> & {\n chains: Chain[]\n logger: Logger\n}\n\n/**\n * Initializes a global instance of the RelayClient\n * https://docs.relay.link/references/sdk/createClient\n */\nexport function initializeRelayClient({\n chains,\n logger,\n ...options\n}: InitializeRelayClientParams): RelayClient {\n return createClient({\n ...options,\n baseApiUrl: MAINNET_RELAY_API,\n chains: chains.map(convertViemChainToRelayChain),\n logger: (message) => {\n logger.info('[RelayClient]:', message)\n },\n })\n}\n\n/**\n * Gets the global instance of the RelayClient\n */\nexport function getRelayClient(): RelayClient {\n const client = getClient()\n\n if (!client) {\n throw new Error('Relay client is not defined')\n }\n\n return client\n}\n", "import { LogLevel } from '@reservoir0x/relay-sdk'\nimport type { Abi, Address } from 'viem'\n\nexport { LogLevel }\n\n// https://docs.relay.link/references/api/get-intents-status-v2\nexport interface RelayExecutionInfo {\n status: RelayExecutionStatus\n details: string\n /** Incoming transaction hashes */\n inTxHashes: string[]\n /** Outgoing transaction hashes */\n txHashes: string[]\n /** The last timestamp the data was updated in milliseconds */\n time: number\n originChainId: number\n destinationChainId: number\n}\n\n// https://docs.relay.link/references/api/get-token-price\nexport interface RelayTokenPriceInfo {\n price: number\n}\n\n//// The types below are duplicated from @funkit/api-base atm, but this package should be used in BE as well\n//// TODO: Are we fine with BE importing @funkit/api-base and (by extension) @funkit/utils?\n//// See https://linear.app/funxyz/issue/PE-1342/sdk-extract-domainsrelayts-to-a-new-package#comment-d487d533\n\nexport interface Logger {\n error(message: string, data?: object): void\n info(message: string, data?: object): void\n}\n\n// Reference: https://github.com/reservoirprotocol/relay-kit/blob/211c645f9702a3b459ff545aa4e2e9d536c38455/packages/sdk/src/types/Execute.ts#L54-L61\nexport enum RelayExecutionStatus {\n DELAYED = 'delayed',\n FAILURE = 'failure',\n PENDING = 'pending',\n REFUND = 'refund',\n SUCCESS = 'success',\n WAITING = 'waiting',\n UNKNOWN = 'unknown',\n}\n\nexport interface ApiFunkitCheckoutActionParams {\n contractAbi: Abi\n contractAddress: Address\n functionName: string\n functionArgs: unknown[]\n value?: bigint\n}\n\nexport enum CheckoutRefundState {\n INITIATED = 'INITIATED',\n ERROR = 'ERROR',\n REFUNDED = 'REFUNDED',\n PROCEEDED = 'PROCEEDED',\n WAITING_FOR_FULFILLMENT = 'WAITING_FOR_FULFILLMENT',\n FULFILLED = 'FULFILLED',\n}\n\n// Reference from api server: https://github.com/fun-xyz/fun-api-server/blob/main/src/tables/FunWalletCheckout.ts#L11C1-L21C2\nexport enum CheckoutState {\n // In-progress States\n FROM_UNFUNDED = 'FROM_UNFUNDED',\n FROM_FUNDED = 'FROM_FUNDED',\n FROM_POOLED = 'FROM_POOLED',\n TO_UNFUNDED = 'TO_UNFUNDED',\n TO_FUNDED = 'TO_FUNDED',\n TO_POOLED = 'TO_POOLED',\n TO_READY = 'TO_READY',\n PENDING_RECEIVAL = 'PENDING_RECEIVAL',\n // Terminal States\n COMPLETED = 'COMPLETED',\n CHECKOUT_ERROR = 'CHECKOUT_ERROR',\n EXPIRED = 'EXPIRED',\n CANCELLED = 'CANCELLED',\n}\n\n// The response of the actual /checkout/quote api\nexport type CheckoutApiQuoteResponse = {\n quoteId: string\n estTotalFromAmountBaseUnit: string\n estSubtotalFromAmountBaseUnit: string\n estFeesFromAmountBaseUnit: string\n fromTokenAddress: Address\n estFeesUsd: number\n estSubtotalUsd: number\n estTotalUsd: number\n estCheckoutTimeMs: number\n estMarketMakerGasUsd: number\n lpFeePercentage: number\n lpFeeUsd: number\n}\n\n// The formatted response quote interface from the core sdk\nexport type CheckoutQuoteResponse = CheckoutApiQuoteResponse & {\n estTotalFromAmount: string\n estSubtotalFromAmount: string\n estFeesFromAmount: string\n\n // Any additional fields purely for frontend use\n metadata?: { [key: string]: unknown }\n}\n", "import type { Address } from 'viem'\nimport { RelayExecutionStatus } from './types'\n\n/**\n * Fake address for a chain's native currency used by Funkit\n */\nexport const FUNKIT_NATIVE_TOKEN =\n '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' satisfies Address\n\n/**\n * Fake address for a chain's native currency used by Relay\n */\nexport const RELAY_NATIVE_TOKEN =\n '0x0000000000000000000000000000000000000000' satisfies Address\n\n/**\n * Wallet that receives the app fees collected by Relay\n */\nexport const FUN_RELAY_REVENUE_WALLET =\n '0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E' satisfies Address\n\n/**\n * Referred field in Relay quote\n */\nexport const FUN_RELAY_REFERRER = 'funxyz'\n\n/**\n * Buffer added to Relay's time estimate (which sometimes is 0)\n */\nexport const RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25_000 // 25 seconds\n\nexport const RELAY_TERMINAL_STATUSES: RelayExecutionStatus[] = [\n RelayExecutionStatus.REFUND,\n RelayExecutionStatus.FAILURE,\n RelayExecutionStatus.SUCCESS,\n]\n", "import {\n type Execute,\n MAINNET_RELAY_API,\n type ProgressData,\n} from '@reservoir0x/relay-sdk'\nimport type { Hex, WalletClient } from 'viem'\nimport { getRelayClient } from './client'\nimport type { Logger, RelayExecutionInfo } from './types'\n\nexport type RelayExecutionStep = ProgressData['currentStep'] & {}\n\nexport interface ExecuteRelayQuoteParams {\n logger: Logger\n onConfirmed: (txHash: Hex) => Promise<void>\n onError: (error: Error) => Promise<void>\n onProgress?: (step: RelayExecutionStep | null) => void\n relayQuote: Execute\n walletClient: WalletClient\n}\n\nexport async function executeRelayQuote({\n logger,\n onConfirmed,\n onError,\n onProgress,\n relayQuote,\n walletClient,\n}: ExecuteRelayQuoteParams) {\n await getRelayClient().actions.execute({\n quote: relayQuote,\n wallet: walletClient,\n onProgress: async ({\n steps,\n fees,\n breakdown,\n currentStep,\n currentStepItem,\n txHashes,\n details,\n error,\n }) => {\n const logPrefix = 'onRelayProgress'\n logger.info(`${logPrefix}:params`, {\n steps,\n currentStep,\n fees,\n breakdown,\n currentStepItem,\n txHashes,\n details,\n error,\n })\n\n onProgress?.(currentStep ?? null)\n\n if (error) {\n logger.info(`${logPrefix}:errorDetected`, error)\n await onError(error).catch((e) => {\n logger.error(`${logPrefix}:onErrorFailed`, e)\n })\n } else if (\n // We can redirect as soon as all the required user steps are done\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1748381169792379\n txHashes &&\n txHashes.length > 0 &&\n txHashes.length === steps.length\n ) {\n logger.info(`${logPrefix}:completed`, txHashes)\n // Can we assume its completed here?\n // Use first txHash as the main txHash in fun DE table\n await onConfirmed(txHashes[0].txHash as Hex).catch((e) => {\n logger.error(`${logPrefix}:onConfirmedFailed`, e)\n })\n }\n },\n })\n}\n\nexport async function getRelayExecutionInfo(\n requestId: string,\n): Promise<RelayExecutionInfo> {\n const url = `${MAINNET_RELAY_API}/intents/status/v2?requestId=${requestId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayExecutionInfo\n}\n", "import type { CallFees } from '@reservoir0x/relay-sdk'\nimport type { Logger } from './types'\n\nexport interface FunRelayFeeItem {\n b: number\n v: number\n}\n\nexport async function getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue,\n clientId,\n}: {\n fromTokenAddress: string\n fromChainId: string\n toTokenAddress: string\n toChainId: string\n estUsdValue: number\n clientId: string\n}): Promise<FunRelayFeeItem> {\n const url = `https://frog.fun.xyz/api/fee?fromTokenAddress=${fromTokenAddress}&fromChainId=${fromChainId}&toTokenAddress=${toTokenAddress}&toChainId=${toChainId}&estUsdValue=${estUsdValue}&clientId=${clientId}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data\n}\n\nexport function parseRelayFees({\n fees,\n logger,\n}: {\n fees: CallFees | undefined\n logger: Logger\n}) {\n // Gas fees, denominated in source chain native token\n const relayGasFeesUsd = Number.parseFloat(fees?.gas?.amountUsd || '0')\n\n // App fees, denominated in source chain token\n const funLpFeesUsd = Number.parseFloat(fees?.app?.amountUsd || '0')\n const funLpFeesFromAmount = Number.parseFloat(\n fees?.app?.amountFormatted || '0',\n )\n const funLpFeesFromAmountBaseUnit = BigInt(fees?.app?.amount || '0')\n\n // Relay fees, denominated in source chain token\n const relayLpFeesUsd =\n Number.parseFloat(fees?.relayer?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerGas?.amountUsd || '0') +\n Number.parseFloat(fees?.relayerService?.amountUsd || '0')\n const relayLpFeesFromAmount =\n Number.parseFloat(fees?.relayer?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerGas?.amountFormatted || '0') +\n Number.parseFloat(fees?.relayerService?.amountFormatted || '0')\n const relayLpFeesFromAmountBaseUnit =\n BigInt(fees?.relayer?.amount || '0') +\n BigInt(fees?.relayerGas?.amount || '0') +\n BigInt(fees?.relayerService?.amount || '0')\n\n const totalLpFeesUsd = funLpFeesUsd + relayLpFeesUsd\n const totalLpFeesFromAmount = funLpFeesFromAmount + relayLpFeesFromAmount\n const totalLpFeesFromAmountBaseUnit =\n funLpFeesFromAmountBaseUnit + relayLpFeesFromAmountBaseUnit\n\n logger.info('parseRelayFees', {\n relayGasFeesUsd,\n funLpFeesUsd,\n funLpFeesFromAmount,\n funLpFeesFromAmountBaseUnit,\n relayLpFeesUsd,\n relayLpFeesFromAmount,\n relayLpFeesFromAmountBaseUnit,\n totalLpFeesUsd,\n totalLpFeesFromAmount,\n totalLpFeesFromAmountBaseUnit,\n })\n\n return {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd: relayGasFeesUsd + totalLpFeesUsd,\n totalFeesFromAmount: totalLpFeesFromAmount,\n totalFeesFromAmountBaseUnit: totalLpFeesFromAmountBaseUnit,\n }\n}\n", "import { MAINNET_RELAY_API } from '@reservoir0x/relay-sdk'\nimport type { RelayTokenPriceInfo } from './types'\n\nexport async function getRelayAssetPriceInfo({\n chainId,\n address,\n}: {\n chainId: string\n address: string\n}): Promise<RelayTokenPriceInfo> {\n const url = `${MAINNET_RELAY_API}/currencies/token/price?chainId=${chainId}&address=${address}`\n const response = await fetch(url)\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data as RelayTokenPriceInfo\n}\n", "import type { Execute, GetQuoteParameters } from '@reservoir0x/relay-sdk'\nimport { type Address, encodeFunctionData } from 'viem'\nimport { getRelayClient } from './client'\nimport {\n FUN_RELAY_REFERRER,\n FUN_RELAY_REVENUE_WALLET,\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n} from './constants'\nimport { getRelayAssetInfo } from './currency'\nimport { getFunRelayFees, parseRelayFees } from './fees'\nimport { getRelayAssetPriceInfo } from './price'\nimport type {\n ApiFunkitCheckoutActionParams,\n CheckoutQuoteResponse,\n Logger,\n} from './types'\nimport { convertFunToRelayTokenAddress } from './utils'\n\ntype RelayQuoteOptions = GetQuoteParameters['options'] & {}\n\nexport type GetRelayQuoteParams = {\n actionParams?: ApiFunkitCheckoutActionParams[]\n fromChainId: string\n fromTokenAddress: Address\n logger: Logger\n /**\n * {@link getRelayQuote} already sets {@link RelayQuoteOptions.appFees|appFees} and {@link RelayQuoteOptions.referrer|referrer}.\n * Only include them if you wish to override.\n */\n options?: RelayQuoteOptions\n recipientAddress: Address | undefined\n toChainId: string\n toTokenAddress: Address\n tradeType: 'EXACT_INPUT' | 'EXACT_OUTPUT'\n userAddress: Address | undefined\n clientId: string\n} & (\n | {\n fromTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_INPUT'\n }\n | {\n toTokenAmountBaseUnit: bigint | string\n tradeType: 'EXACT_OUTPUT'\n }\n)\n\nexport type RelayQuote = CheckoutQuoteResponse & {\n /** Required for EXACT_INPUT checkouts */\n finalToAmountBaseUnit: string\n metadata: {\n fromAmountBaseUnit: string\n relayQuote: Execute\n toAmountBaseUnit: string\n }\n}\n\nasync function getQuoteEstUsdValue({\n tokenChainId,\n tokenAddress,\n tokenAmountBaseUnit,\n logger,\n}: {\n tokenChainId: string\n tokenAddress: string\n tokenAmountBaseUnit: string\n logger: Logger\n}) {\n try {\n const [tokenPriceRes, tokenInfoRes] = await Promise.all([\n getRelayAssetPriceInfo({\n chainId: tokenChainId,\n address: convertFunToRelayTokenAddress(tokenAddress as Address),\n }),\n getRelayAssetInfo({\n chainId: tokenChainId,\n address: convertFunToRelayTokenAddress(tokenAddress as Address),\n }),\n ])\n\n const price = tokenPriceRes.price\n const decimals = tokenInfoRes.decimals\n\n const absoluteAmount = BigInt(tokenAmountBaseUnit) / BigInt(10 ** decimals)\n return Number(price) * Number(absoluteAmount)\n } catch (err) {\n logger.error('getQuoteEstUsdValueError', {\n message: `Failed to get USD value for token ${tokenAddress} on chain ${tokenChainId}: ${\n err instanceof Error ? err.message : JSON.stringify(err)\n }. Falling back to 0 USD.`,\n })\n // If any part fails, just fallback to 0 USD so that we do not block quote\n return 0\n }\n}\n\nexport async function getRelayQuote({\n logger,\n ...params\n}: GetRelayQuoteParams): Promise<RelayQuote> {\n const {\n actionParams,\n fromChainId,\n fromTokenAddress,\n options,\n recipientAddress,\n toChainId,\n toTokenAddress,\n userAddress,\n clientId,\n } = params\n\n try {\n const relayClient = getRelayClient()\n\n const txs = actionParams?.map((action) => {\n const data = encodeFunctionData({\n abi: action.contractAbi,\n args: action.functionArgs,\n functionName: action.functionName,\n })\n\n return {\n data,\n to: action.contractAddress,\n value: String(action.value ?? 0n),\n }\n })\n\n const isExactIn = params.tradeType === 'EXACT_INPUT'\n const queryTokenAmountBaseUnit = isExactIn\n ? params.fromTokenAmountBaseUnit\n : params.toTokenAmountBaseUnit\n const queryTokenAddress = isExactIn ? fromTokenAddress : toTokenAddress\n const queryTokenChainId = isExactIn ? fromChainId : toChainId\n\n const estUsdValue = await getQuoteEstUsdValue({\n tokenChainId: queryTokenChainId,\n tokenAddress: queryTokenAddress,\n tokenAmountBaseUnit: queryTokenAmountBaseUnit.toString(),\n logger,\n })\n\n const feeInfo = await getFunRelayFees({\n fromTokenAddress,\n fromChainId,\n toTokenAddress,\n toChainId,\n estUsdValue: Number(estUsdValue) || 0,\n clientId,\n })\n\n const appFeeBp = feeInfo.b + feeInfo.v\n\n logger.info('getRelayQuoteParams', {\n ...params,\n queryTokenAmountBaseUnit,\n txs,\n estUsdValue,\n feeInfo,\n appFeeBp,\n })\n\n // Get the full quote with fees\n const relayQuote = await relayClient.actions.getQuote({\n chainId: Number(fromChainId),\n toChainId: Number(toChainId),\n currency: convertFunToRelayTokenAddress(fromTokenAddress),\n toCurrency: convertFunToRelayTokenAddress(toTokenAddress),\n amount: queryTokenAmountBaseUnit.toString(),\n recipient: recipientAddress,\n tradeType: params.tradeType,\n user: userAddress,\n ...(txs && { txs }),\n options: {\n referrer: clientId\n ? `${FUN_RELAY_REFERRER}|${clientId}`\n : FUN_RELAY_REFERRER,\n appFees: [\n {\n fee: appFeeBp.toString(),\n recipient: FUN_RELAY_REVENUE_WALLET,\n },\n ],\n ...options,\n },\n })\n\n logger.info('relayQuote', relayQuote)\n\n const estSubtotalUsd = Number(\n relayQuote.details?.currencyOut?.amountUsd || 0,\n )\n const estTotalUsd = Number(relayQuote.details?.currencyIn?.amountUsd || 0)\n // Get how much fromAmount is needed for the quote\n const fromAmountString =\n relayQuote.details?.currencyIn?.amountFormatted || '0'\n const fromAmountBaseUnitString =\n relayQuote.details?.currencyIn?.amount || '0'\n\n // RequestID will be consistent across steps in the quote\n // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1747774944603209\n const relayRequestId = relayQuote.steps[0]?.requestId\n\n // TODO: Verify with relay team if this is possible?\n if (!relayRequestId) {\n throw new Error('Relay quote does not contain a requestId')\n }\n\n // TODO: Verify with relay team if this is possible?\n if (!relayQuote.details?.currencyIn || !relayQuote.details?.currencyOut) {\n throw new Error('Relay quote does not contain trade details')\n }\n\n const {\n relayGasFeesUsd,\n totalLpFeesUsd,\n totalFeesUsd,\n totalFeesFromAmount,\n totalFeesFromAmountBaseUnit,\n } = parseRelayFees({ fees: relayQuote.fees, logger })\n\n const estSubtotalFromAmount = (\n Number.parseFloat(fromAmountString) - totalFeesFromAmount\n ).toString()\n\n const estSubtotalFromAmountBaseUnit = (\n BigInt(fromAmountBaseUnitString) - totalFeesFromAmountBaseUnit\n ).toString()\n\n return {\n quoteId: relayRequestId,\n estCheckoutTimeMs:\n (relayQuote.details.timeEstimate || 0) * 1000 +\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n estFeesFromAmount: totalFeesFromAmount.toString(),\n estFeesFromAmountBaseUnit: totalFeesFromAmountBaseUnit.toString(),\n estFeesUsd: totalFeesUsd,\n estMarketMakerGasUsd: relayGasFeesUsd,\n estSubtotalFromAmount,\n estSubtotalFromAmountBaseUnit,\n estSubtotalUsd,\n estTotalFromAmount: fromAmountString,\n estTotalFromAmountBaseUnit: fromAmountBaseUnitString,\n estTotalUsd,\n finalToAmountBaseUnit: relayQuote.details.currencyOut.amount ?? '0', // TODO: Or do we want 'minimumAmount'?\n fromTokenAddress,\n lpFeePercentage: 0, // TODO: ?\n lpFeeUsd: totalLpFeesUsd,\n metadata: {\n fromAmountBaseUnit: isExactIn\n ? queryTokenAmountBaseUnit.toString()\n : (relayQuote.details.currencyIn.amount ?? '0'),\n relayQuote,\n toAmountBaseUnit: isExactIn\n ? (relayQuote.details.currencyOut.amount ?? '0')\n : queryTokenAmountBaseUnit.toString(),\n },\n }\n } catch (err) {\n throw new Error(\n `An error occurred trying to generate a relay quote: ${\n err instanceof Error ? err.message : JSON.stringify(err)\n }`,\n )\n }\n}\n", "import { MAINNET_RELAY_API } from '@reservoir0x/relay-sdk'\n\nexport interface RelayTokenInfo {\n chainId: number\n address: string\n symbol: string\n name: string\n decimals: number\n vmType: string\n metadata: {\n logoURI: string\n verified: boolean\n isNative: boolean\n }\n}\n\nexport async function getRelayAssetInfo({\n chainId,\n address,\n}: {\n chainId: string\n address: string\n}): Promise<RelayTokenInfo> {\n const url = `${MAINNET_RELAY_API}/currencies/v2`\n const body = {\n chainIds: [chainId],\n address,\n }\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n throw Error(response.statusText)\n }\n\n const data = await response.json()\n return data?.[0] as RelayTokenInfo\n}\n", "import type { Address } from 'viem'\nimport {\n FUNKIT_NATIVE_TOKEN,\n RELAY_NATIVE_TOKEN,\n RELAY_TERMINAL_STATUSES,\n} from './constants'\nimport {\n CheckoutRefundState,\n CheckoutState,\n type RelayExecutionInfo,\n} from './types'\n\n/**\n * Converts a token address within Funkit the corresponding Relay token address.\n */\nexport function convertFunToRelayTokenAddress(address: Address): Address {\n if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {\n return RELAY_NATIVE_TOKEN\n }\n\n return address\n}\n\nexport function getRelayExecutionRefundState(\n info: RelayExecutionInfo,\n): CheckoutRefundState | undefined {\n switch (info.status) {\n case 'refund':\n return CheckoutRefundState.REFUNDED\n default:\n return undefined\n }\n}\n\nexport function getRelayExecutionState(\n info: RelayExecutionInfo,\n): CheckoutState {\n switch (info.status) {\n case 'success':\n return CheckoutState.COMPLETED\n case 'failure':\n case 'refund':\n return CheckoutState.CHECKOUT_ERROR\n default:\n return CheckoutState.PENDING_RECEIVAL\n }\n}\n\n/**\n * Checks whether the Relay execution has reached a terminal status.\n */\nexport function isRelayExecutionTerminalStatus(\n info: RelayExecutionInfo,\n): boolean {\n return RELAY_TERMINAL_STATUSES.includes(info.status)\n}\n"],
5
+ "mappings": ";AAAA;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgBA,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA6C;AAC3C,SAAO,aAAa;AAAA,IAClB,GAAG;AAAA,IACH,YAAY;AAAA,IACZ,QAAQ,OAAO,IAAI,4BAA4B;AAAA,IAC/C,QAAQ,CAAC,YAAY;AACnB,aAAO,KAAK,kBAAkB,OAAO;AAAA,IACvC;AAAA,EACF,CAAC;AACH;AAKO,SAAS,iBAA8B;AAC5C,QAAM,SAAS,UAAU;AAEzB,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,6BAA6B;AAAA,EAC/C;AAEA,SAAO;AACT;;;ACjDA,SAAS,gBAAgB;;;ACMlB,IAAM,sBACX;AAKK,IAAM,qBACX;AAKK,IAAM,2BACX;AAKK,IAAM,qBAAqB;AAK3B,IAAM,sCAAsC;AAE5C,IAAM,0BAAkD;AAAA;AAAA;AAAA;AAI/D;;;ACnCA;AAAA,EAEE,qBAAAA;AAAA,OAEK;AAgBP,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,eAAe,EAAE,QAAQ,QAAQ;AAAA,IACrC,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAAM;AACJ,YAAM,YAAY;AAClB,aAAO,KAAK,GAAG,SAAS,WAAW;AAAA,QACjC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,mBAAa,eAAe,IAAI;AAEhC,UAAI,OAAO;AACT,eAAO,KAAK,GAAG,SAAS,kBAAkB,KAAK;AAC/C,cAAM,QAAQ,KAAK,EAAE,MAAM,CAAC,MAAM;AAChC,iBAAO,MAAM,GAAG,SAAS,kBAAkB,CAAC;AAAA,QAC9C,CAAC;AAAA,MACH;AAAA;AAAA;AAAA,QAGE,YACA,SAAS,SAAS,KAClB,SAAS,WAAW,MAAM;AAAA,QAC1B;AACA,eAAO,KAAK,GAAG,SAAS,cAAc,QAAQ;AAG9C,cAAM,YAAY,SAAS,CAAC,EAAE,MAAa,EAAE,MAAM,CAAC,MAAM;AACxD,iBAAO,MAAM,GAAG,SAAS,sBAAsB,CAAC;AAAA,QAClD,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,sBACpB,WAC6B;AAC7B,QAAM,MAAM,GAAGC,kBAAiB,gCAAgC,SAAS;AACzE,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,MAAM,SAAS,UAAU;AAAA,EACjC;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,SAAO;AACT;;;ACjFA,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAO6B;AAC3B,QAAM,MAAM,iDAAiD,gBAAgB,gBAAgB,WAAW,mBAAmB,cAAc,cAAc,SAAS,gBAAgB,WAAW,aAAa,QAAQ;AAChN,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,MAAM,SAAS,UAAU;AAAA,EACjC;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,SAAO;AACT;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAGG;AAED,QAAM,kBAAkB,OAAO,WAAW,MAAM,KAAK,aAAa,GAAG;AAGrE,QAAM,eAAe,OAAO,WAAW,MAAM,KAAK,aAAa,GAAG;AAClE,QAAM,sBAAsB,OAAO;AAAA,IACjC,MAAM,KAAK,mBAAmB;AAAA,EAChC;AACA,QAAM,8BAA8B,OAAO,MAAM,KAAK,UAAU,GAAG;AAGnE,QAAM,iBACJ,OAAO,WAAW,MAAM,SAAS,aAAa,GAAG,IACjD,OAAO,WAAW,MAAM,YAAY,aAAa,GAAG,IACpD,OAAO,WAAW,MAAM,gBAAgB,aAAa,GAAG;AAC1D,QAAM,wBACJ,OAAO,WAAW,MAAM,SAAS,mBAAmB,GAAG,IACvD,OAAO,WAAW,MAAM,YAAY,mBAAmB,GAAG,IAC1D,OAAO,WAAW,MAAM,gBAAgB,mBAAmB,GAAG;AAChE,QAAM,gCACJ,OAAO,MAAM,SAAS,UAAU,GAAG,IACnC,OAAO,MAAM,YAAY,UAAU,GAAG,IACtC,OAAO,MAAM,gBAAgB,UAAU,GAAG;AAE5C,QAAM,iBAAiB,eAAe;AACtC,QAAM,wBAAwB,sBAAsB;AACpD,QAAM,gCACJ,8BAA8B;AAEhC,SAAO,KAAK,kBAAkB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,cAAc,kBAAkB;AAAA,IAChC,qBAAqB;AAAA,IACrB,6BAA6B;AAAA,EAC/B;AACF;;;ACzFA,SAAS,qBAAAC,0BAAyB;AAGlC,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA;AACF,GAGiC;AAC/B,QAAM,MAAM,GAAGA,kBAAiB,mCAAmC,OAAO,YAAY,OAAO;AAC7F,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,MAAM,SAAS,UAAU;AAAA,EACjC;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,SAAO;AACT;;;ACjBA,SAAuB,0BAA0B;;;ACDjD,SAAS,qBAAAC,0BAAyB;AAgBlC,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AACF,GAG4B;AAC1B,QAAM,MAAM,GAAGA,kBAAiB;AAChC,QAAM,OAAO;AAAA,IACX,UAAU,CAAC,OAAO;AAAA,IAClB;AAAA,EACF;AACA,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,MAAM,SAAS,UAAU;AAAA,EACjC;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,SAAO,OAAO,CAAC;AACjB;;;ACxBO,SAAS,8BAA8B,SAA2B;AACvE,MAAI,QAAQ,YAAY,MAAM,oBAAoB,YAAY,GAAG;AAC/D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,6BACd,MACiC;AACjC,UAAQ,KAAK,QAAQ;AAAA,IACnB,KAAK;AACH;AAAA,IACF;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,uBACd,MACe;AACf,UAAQ,KAAK,QAAQ;AAAA,IACnB,KAAK;AACH;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH;AAAA,IACF;AACE;AAAA,EACJ;AACF;AAKO,SAAS,+BACd,MACS;AACT,SAAO,wBAAwB,SAAS,KAAK,MAAM;AACrD;;;AFEA,eAAe,oBAAoB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,MAAI;AACF,UAAM,CAAC,eAAe,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,MACtD,uBAAuB;AAAA,QACrB,SAAS;AAAA,QACT,SAAS,8BAA8B,YAAuB;AAAA,MAChE,CAAC;AAAA,MACD,kBAAkB;AAAA,QAChB,SAAS;AAAA,QACT,SAAS,8BAA8B,YAAuB;AAAA,MAChE,CAAC;AAAA,IACH,CAAC;AAED,UAAM,QAAQ,cAAc;AAC5B,UAAM,WAAW,aAAa;AAE9B,UAAM,iBAAiB,OAAO,mBAAmB,IAAI,OAAO,MAAM,QAAQ;AAC1E,WAAO,OAAO,KAAK,IAAI,OAAO,cAAc;AAAA,EAC9C,SAAS,KAAK;AACZ,WAAO,MAAM,4BAA4B;AAAA,MACvC,SAAS,qCAAqC,YAAY,aAAa,YAAY,KACjF,eAAe,QAAQ,IAAI,UAAU,KAAK,UAAU,GAAG,CACzD;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,cAAc;AAAA,EAClC;AAAA,EACA,GAAG;AACL,GAA6C;AAC3C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,MAAI;AACF,UAAM,cAAc,eAAe;AAEnC,UAAM,MAAM,cAAc,IAAI,CAAC,WAAW;AACxC,YAAM,OAAO,mBAAmB;AAAA,QAC9B,KAAK,OAAO;AAAA,QACZ,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,MACvB,CAAC;AAED,aAAO;AAAA,QACL;AAAA,QACA,IAAI,OAAO;AAAA,QACX,OAAO,OAAO,OAAO,SAAS,EAAE;AAAA,MAClC;AAAA,IACF,CAAC;AAED,UAAM,YAAY,OAAO,cAAc;AACvC,UAAM,2BAA2B,YAC7B,OAAO,0BACP,OAAO;AACX,UAAM,oBAAoB,YAAY,mBAAmB;AACzD,UAAM,oBAAoB,YAAY,cAAc;AAEpD,UAAM,cAAc,MAAM,oBAAoB;AAAA,MAC5C,cAAc;AAAA,MACd,cAAc;AAAA,MACd,qBAAqB,yBAAyB,SAAS;AAAA,MACvD;AAAA,IACF,CAAC;AAED,UAAM,UAAU,MAAM,gBAAgB;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,OAAO,WAAW,KAAK;AAAA,MACpC;AAAA,IACF,CAAC;AAED,UAAM,WAAW,QAAQ,IAAI,QAAQ;AAErC,WAAO,KAAK,uBAAuB;AAAA,MACjC,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,UAAM,aAAa,MAAM,YAAY,QAAQ,SAAS;AAAA,MACpD,SAAS,OAAO,WAAW;AAAA,MAC3B,WAAW,OAAO,SAAS;AAAA,MAC3B,UAAU,8BAA8B,gBAAgB;AAAA,MACxD,YAAY,8BAA8B,cAAc;AAAA,MACxD,QAAQ,yBAAyB,SAAS;AAAA,MAC1C,WAAW;AAAA,MACX,WAAW,OAAO;AAAA,MAClB,MAAM;AAAA,MACN,GAAI,OAAO,EAAE,IAAI;AAAA,MACjB,SAAS;AAAA,QACP,UAAU,WACN,GAAG,kBAAkB,IAAI,QAAQ,KACjC;AAAA,QACJ,SAAS;AAAA,UACP;AAAA,YACE,KAAK,SAAS,SAAS;AAAA,YACvB,WAAW;AAAA,UACb;AAAA,QACF;AAAA,QACA,GAAG;AAAA,MACL;AAAA,IACF,CAAC;AAED,WAAO,KAAK,cAAc,UAAU;AAEpC,UAAM,iBAAiB;AAAA,MACrB,WAAW,SAAS,aAAa,aAAa;AAAA,IAChD;AACA,UAAM,cAAc,OAAO,WAAW,SAAS,YAAY,aAAa,CAAC;AAEzE,UAAM,mBACJ,WAAW,SAAS,YAAY,mBAAmB;AACrD,UAAM,2BACJ,WAAW,SAAS,YAAY,UAAU;AAI5C,UAAM,iBAAiB,WAAW,MAAM,CAAC,GAAG;AAG5C,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAGA,QAAI,CAAC,WAAW,SAAS,cAAc,CAAC,WAAW,SAAS,aAAa;AACvE,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,eAAe,EAAE,MAAM,WAAW,MAAM,OAAO,CAAC;AAEpD,UAAM,yBACJ,OAAO,WAAW,gBAAgB,IAAI,qBACtC,SAAS;AAEX,UAAM,iCACJ,OAAO,wBAAwB,IAAI,6BACnC,SAAS;AAEX,WAAO;AAAA,MACL,SAAS;AAAA,MACT,oBACG,WAAW,QAAQ,gBAAgB,KAAK,MACzC;AAAA,MACF,mBAAmB,oBAAoB,SAAS;AAAA,MAChD,2BAA2B,4BAA4B,SAAS;AAAA,MAChE,YAAY;AAAA,MACZ,sBAAsB;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA,oBAAoB;AAAA,MACpB,4BAA4B;AAAA,MAC5B;AAAA,MACA,uBAAuB,WAAW,QAAQ,YAAY,UAAU;AAAA;AAAA,MAChE;AAAA,MACA,iBAAiB;AAAA;AAAA,MACjB,UAAU;AAAA,MACV,UAAU;AAAA,QACR,oBAAoB,YAChB,yBAAyB,SAAS,IACjC,WAAW,QAAQ,WAAW,UAAU;AAAA,QAC7C;AAAA,QACA,kBAAkB,YACb,WAAW,QAAQ,YAAY,UAAU,MAC1C,yBAAyB,SAAS;AAAA,MACxC;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,uDACE,eAAe,QAAQ,IAAI,UAAU,KAAK,UAAU,GAAG,CACzD;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": ["MAINNET_RELAY_API", "MAINNET_RELAY_API", "MAINNET_RELAY_API", "MAINNET_RELAY_API"]
7
7
  }
@@ -0,0 +1,18 @@
1
+ export interface RelayTokenInfo {
2
+ chainId: number;
3
+ address: string;
4
+ symbol: string;
5
+ name: string;
6
+ decimals: number;
7
+ vmType: string;
8
+ metadata: {
9
+ logoURI: string;
10
+ verified: boolean;
11
+ isNative: boolean;
12
+ };
13
+ }
14
+ export declare function getRelayAssetInfo({ chainId, address, }: {
15
+ chainId: string;
16
+ address: string;
17
+ }): Promise<RelayTokenInfo>;
18
+ //# sourceMappingURL=currency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../../src/currency.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,OAAO,CAAA;QACjB,QAAQ,EAAE,OAAO,CAAA;KAClB,CAAA;CACF;AAED,wBAAsB,iBAAiB,CAAC,EACtC,OAAO,EACP,OAAO,GACR,EAAE;IACD,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,cAAc,CAAC,CAiB1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../src/quote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,MAAM,CAAA;AAQvD,OAAO,KAAK,EACV,6BAA6B,EAC7B,qBAAqB,EACrB,MAAM,EACP,MAAM,SAAS,CAAA;AAGhB,KAAK,iBAAiB,GAAG,kBAAkB,CAAC,SAAS,CAAC,GAAG,EAAE,CAAA;AAE3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,CAAC,EAAE,6BAA6B,EAAE,CAAA;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,OAAO,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,SAAS,EAAE,aAAa,GAAG,cAAc,CAAA;IACzC,WAAW,EAAE,OAAO,GAAG,SAAS,CAAA;IAChC,QAAQ,EAAE,MAAM,CAAA;CACjB,GAAG,CACA;IACE,uBAAuB,EAAE,MAAM,GAAG,MAAM,CAAA;IACxC,SAAS,EAAE,aAAa,CAAA;CACzB,GACD;IACE,qBAAqB,EAAE,MAAM,GAAG,MAAM,CAAA;IACtC,SAAS,EAAE,cAAc,CAAA;CAC1B,CACJ,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,qBAAqB,GAAG;IAC/C,yCAAyC;IACzC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,QAAQ,EAAE;QACR,kBAAkB,EAAE,MAAM,CAAA;QAC1B,UAAU,EAAE,OAAO,CAAA;QACnB,gBAAgB,EAAE,MAAM,CAAA;KACzB,CAAA;CACF,CAAA;AAED,wBAAsB,aAAa,CAAC,EAClC,MAAM,EACN,GAAG,MAAM,EACV,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CA+K3C"}
1
+ {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../src/quote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,MAAM,CAAA;AAUvD,OAAO,KAAK,EACV,6BAA6B,EAC7B,qBAAqB,EACrB,MAAM,EACP,MAAM,SAAS,CAAA;AAGhB,KAAK,iBAAiB,GAAG,kBAAkB,CAAC,SAAS,CAAC,GAAG,EAAE,CAAA;AAE3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,CAAC,EAAE,6BAA6B,EAAE,CAAA;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,OAAO,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,SAAS,EAAE,aAAa,GAAG,cAAc,CAAA;IACzC,WAAW,EAAE,OAAO,GAAG,SAAS,CAAA;IAChC,QAAQ,EAAE,MAAM,CAAA;CACjB,GAAG,CACA;IACE,uBAAuB,EAAE,MAAM,GAAG,MAAM,CAAA;IACxC,SAAS,EAAE,aAAa,CAAA;CACzB,GACD;IACE,qBAAqB,EAAE,MAAM,GAAG,MAAM,CAAA;IACtC,SAAS,EAAE,cAAc,CAAA;CAC1B,CACJ,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,qBAAqB,GAAG;IAC/C,yCAAyC;IACzC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,QAAQ,EAAE;QACR,kBAAkB,EAAE,MAAM,CAAA;QAC1B,UAAU,EAAE,OAAO,CAAA;QACnB,gBAAgB,EAAE,MAAM,CAAA;KACzB,CAAA;CACF,CAAA;AAyCD,wBAAsB,aAAa,CAAC,EAClC,MAAM,EACN,GAAG,MAAM,EACV,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAuK3C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funkit/fun-relay",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "files": [
5
5
  "dist/src",
6
6
  "dist/index.d.ts",