@funkit/fun-relay 0.1.3 → 0.1.5
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 +14 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -12
- package/dist/index.js.map +2 -2
- package/dist/index.mjs +46 -12
- package/dist/index.mjs.map +2 -2
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/fees.d.ts +12 -3
- package/dist/src/fees.d.ts.map +1 -1
- package/dist/src/quote.d.ts +1 -0
- package/dist/src/quote.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @funkit/fun-relay
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fc10b40: refactor: buffer and chain consts
|
|
8
|
+
- 1137afa: feat: implement dynamic fees
|
|
9
|
+
- 43cf1bf: feat: dynamic relay referrer
|
|
10
|
+
|
|
11
|
+
## 0.1.4
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 0557854: refactor: bump buffer to 6s
|
|
16
|
+
|
|
3
17
|
## 0.1.3
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { getRelayClient, initializeRelayClient, type InitializeRelayClientParams, } from './src/client';
|
|
2
2
|
export { FUN_RELAY_REFERRER, FUN_RELAY_REVENUE_WALLET, RELAY_TERMINAL_STATUSES, } from './src/constants';
|
|
3
3
|
export { type ExecuteRelayQuoteParams, executeRelayQuote, getRelayExecutionInfo, } from './src/execution';
|
|
4
|
-
export {
|
|
4
|
+
export { parseRelayFees } from './src/fees';
|
|
5
5
|
export { getRelayAssetPriceInfo } from './src/price';
|
|
6
6
|
export { type GetRelayQuoteParams, getRelayQuote, type RelayQuote, } from './src/quote';
|
|
7
7
|
export { getRelayExecutionRefundState, getRelayExecutionState, isRelayExecutionTerminalStatus, convertFunToRelayTokenAddress, } from './src/utils';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,KAAK,2BAA2B,GACjC,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,KAAK,uBAAuB,EAC5B,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,iBAAiB,CAAA;AACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,KAAK,2BAA2B,GACjC,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,KAAK,uBAAuB,EAC5B,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EACL,KAAK,mBAAmB,EACxB,aAAa,EACb,KAAK,UAAU,GAChB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,8BAA8B,EAC9B,6BAA6B,GAC9B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,QAAQ,EACR,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,6 @@ __export(index_exports, {
|
|
|
24
24
|
FUN_RELAY_REVENUE_WALLET: () => FUN_RELAY_REVENUE_WALLET,
|
|
25
25
|
LogLevel: () => import_relay_sdk2.LogLevel,
|
|
26
26
|
RELAY_TERMINAL_STATUSES: () => RELAY_TERMINAL_STATUSES,
|
|
27
|
-
computeFunRelayFeeBps: () => computeFunRelayFeeBps,
|
|
28
27
|
convertFunToRelayTokenAddress: () => convertFunToRelayTokenAddress,
|
|
29
28
|
executeRelayQuote: () => executeRelayQuote,
|
|
30
29
|
getRelayAssetPriceInfo: () => getRelayAssetPriceInfo,
|
|
@@ -71,7 +70,7 @@ var FUNKIT_NATIVE_TOKEN = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
|
|
71
70
|
var RELAY_NATIVE_TOKEN = "0x0000000000000000000000000000000000000000";
|
|
72
71
|
var FUN_RELAY_REVENUE_WALLET = "0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E";
|
|
73
72
|
var FUN_RELAY_REFERRER = "funxyz";
|
|
74
|
-
var RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS =
|
|
73
|
+
var RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25e3;
|
|
75
74
|
var RELAY_TERMINAL_STATUSES = [
|
|
76
75
|
"refund" /* REFUND */,
|
|
77
76
|
"failure" /* FAILURE */,
|
|
@@ -142,10 +141,21 @@ async function getRelayExecutionInfo(requestId) {
|
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
// src/fees.ts
|
|
145
|
-
function
|
|
146
|
-
|
|
144
|
+
async function getFunRelayFees({
|
|
145
|
+
fromTokenAddress,
|
|
146
|
+
fromChainId,
|
|
147
|
+
toTokenAddress,
|
|
148
|
+
toChainId,
|
|
149
|
+
estUsdValue,
|
|
150
|
+
clientId
|
|
147
151
|
}) {
|
|
148
|
-
|
|
152
|
+
const url = `https://frog.fun.xyz/api/fee?fromTokenAddress=${fromTokenAddress}&fromChainId=${fromChainId}&toTokenAddress=${toTokenAddress}&toChainId=${toChainId}&estUsdValue=${estUsdValue}&clientId=${clientId}`;
|
|
153
|
+
const response = await fetch(url);
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
throw Error(response.statusText);
|
|
156
|
+
}
|
|
157
|
+
const data = await response.json();
|
|
158
|
+
return data;
|
|
149
159
|
}
|
|
150
160
|
function parseRelayFees({
|
|
151
161
|
fees,
|
|
@@ -245,11 +255,13 @@ async function getRelayQuote({
|
|
|
245
255
|
recipientAddress,
|
|
246
256
|
toChainId,
|
|
247
257
|
toTokenAddress,
|
|
248
|
-
userAddress
|
|
258
|
+
userAddress,
|
|
259
|
+
clientId
|
|
249
260
|
} = params;
|
|
250
261
|
try {
|
|
251
262
|
const relayClient = getRelayClient();
|
|
252
|
-
const
|
|
263
|
+
const isExactIn = params.tradeType === "EXACT_INPUT";
|
|
264
|
+
const tokenAmountBaseUnit = isExactIn ? params.fromTokenAmountBaseUnit : params.toTokenAmountBaseUnit;
|
|
253
265
|
const txs = actionParams?.map((action) => {
|
|
254
266
|
const data = (0, import_viem.encodeFunctionData)({
|
|
255
267
|
abi: action.contractAbi,
|
|
@@ -262,10 +274,34 @@ async function getRelayQuote({
|
|
|
262
274
|
value: String(action.value ?? 0n)
|
|
263
275
|
};
|
|
264
276
|
});
|
|
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
|
|
287
|
+
});
|
|
288
|
+
const estUsdValue = priceInfo.details?.currencyIn?.amountUsd;
|
|
289
|
+
const feeInfo = await getFunRelayFees({
|
|
290
|
+
fromTokenAddress,
|
|
291
|
+
fromChainId,
|
|
292
|
+
toTokenAddress,
|
|
293
|
+
toChainId,
|
|
294
|
+
estUsdValue: Number(estUsdValue) || 0,
|
|
295
|
+
clientId
|
|
296
|
+
});
|
|
297
|
+
const appFeeBp = feeInfo.b + feeInfo.v;
|
|
265
298
|
logger.info("getRelayQuoteParams", {
|
|
266
299
|
...params,
|
|
267
300
|
tokenAmountBaseUnit,
|
|
268
|
-
txs
|
|
301
|
+
txs,
|
|
302
|
+
priceInfo,
|
|
303
|
+
feeInfo,
|
|
304
|
+
appFeeBp
|
|
269
305
|
});
|
|
270
306
|
const relayQuote = await relayClient.actions.getQuote({
|
|
271
307
|
chainId: Number(fromChainId),
|
|
@@ -278,12 +314,10 @@ async function getRelayQuote({
|
|
|
278
314
|
user: userAddress,
|
|
279
315
|
...txs && { txs },
|
|
280
316
|
options: {
|
|
281
|
-
referrer: FUN_RELAY_REFERRER,
|
|
317
|
+
referrer: clientId ? `${FUN_RELAY_REFERRER}|${clientId}` : FUN_RELAY_REFERRER,
|
|
282
318
|
appFees: [
|
|
283
319
|
{
|
|
284
|
-
fee:
|
|
285
|
-
isSameToken: fromChainId === toChainId && fromTokenAddress.toLowerCase() === toTokenAddress.toLowerCase()
|
|
286
|
-
}).toString(),
|
|
320
|
+
fee: appFeeBp.toString(),
|
|
287
321
|
recipient: FUN_RELAY_REVENUE_WALLET
|
|
288
322
|
}
|
|
289
323
|
],
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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 {\n computeFunRelayFeeBps,\n parseRelayFees,\n} 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 = 3_000 // 3 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 function computeFunRelayFeeBps({\n isSameToken,\n}: {\n isSameToken: boolean\n}): number {\n // For now, we have a flat 2bps app fee for all relay transactions\n // TODO: Dynamic fee based on the transaction size, from token, to token, etc\n return isSameToken ? 0 : 2\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 { computeFunRelayFeeBps, 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} & (\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 } = params\n\n try {\n const relayClient = getRelayClient()\n\n const tokenAmountBaseUnit =\n params.tradeType === 'EXACT_INPUT'\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 logger.info('getRelayQuoteParams', {\n ...params,\n tokenAmountBaseUnit,\n txs,\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: FUN_RELAY_REFERRER,\n appFees: [\n {\n fee: computeFunRelayFeeBps({\n isSameToken:\n fromChainId === toChainId &&\n fromTokenAddress.toLowerCase() === toTokenAddress.toLowerCase(),\n }).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": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA
|
|
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
6
|
"names": ["import_relay_sdk", "import_relay_sdk", "import_relay_sdk"]
|
|
7
7
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -35,7 +35,7 @@ var FUNKIT_NATIVE_TOKEN = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
|
|
35
35
|
var RELAY_NATIVE_TOKEN = "0x0000000000000000000000000000000000000000";
|
|
36
36
|
var FUN_RELAY_REVENUE_WALLET = "0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E";
|
|
37
37
|
var FUN_RELAY_REFERRER = "funxyz";
|
|
38
|
-
var RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS =
|
|
38
|
+
var RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25e3;
|
|
39
39
|
var RELAY_TERMINAL_STATUSES = [
|
|
40
40
|
"refund" /* REFUND */,
|
|
41
41
|
"failure" /* FAILURE */,
|
|
@@ -108,10 +108,21 @@ async function getRelayExecutionInfo(requestId) {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
// src/fees.ts
|
|
111
|
-
function
|
|
112
|
-
|
|
111
|
+
async function getFunRelayFees({
|
|
112
|
+
fromTokenAddress,
|
|
113
|
+
fromChainId,
|
|
114
|
+
toTokenAddress,
|
|
115
|
+
toChainId,
|
|
116
|
+
estUsdValue,
|
|
117
|
+
clientId
|
|
113
118
|
}) {
|
|
114
|
-
|
|
119
|
+
const url = `https://frog.fun.xyz/api/fee?fromTokenAddress=${fromTokenAddress}&fromChainId=${fromChainId}&toTokenAddress=${toTokenAddress}&toChainId=${toChainId}&estUsdValue=${estUsdValue}&clientId=${clientId}`;
|
|
120
|
+
const response = await fetch(url);
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
throw Error(response.statusText);
|
|
123
|
+
}
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
return data;
|
|
115
126
|
}
|
|
116
127
|
function parseRelayFees({
|
|
117
128
|
fees,
|
|
@@ -211,11 +222,13 @@ async function getRelayQuote({
|
|
|
211
222
|
recipientAddress,
|
|
212
223
|
toChainId,
|
|
213
224
|
toTokenAddress,
|
|
214
|
-
userAddress
|
|
225
|
+
userAddress,
|
|
226
|
+
clientId
|
|
215
227
|
} = params;
|
|
216
228
|
try {
|
|
217
229
|
const relayClient = getRelayClient();
|
|
218
|
-
const
|
|
230
|
+
const isExactIn = params.tradeType === "EXACT_INPUT";
|
|
231
|
+
const tokenAmountBaseUnit = isExactIn ? params.fromTokenAmountBaseUnit : params.toTokenAmountBaseUnit;
|
|
219
232
|
const txs = actionParams?.map((action) => {
|
|
220
233
|
const data = encodeFunctionData({
|
|
221
234
|
abi: action.contractAbi,
|
|
@@ -228,10 +241,34 @@ async function getRelayQuote({
|
|
|
228
241
|
value: String(action.value ?? 0n)
|
|
229
242
|
};
|
|
230
243
|
});
|
|
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
|
|
254
|
+
});
|
|
255
|
+
const estUsdValue = priceInfo.details?.currencyIn?.amountUsd;
|
|
256
|
+
const feeInfo = await getFunRelayFees({
|
|
257
|
+
fromTokenAddress,
|
|
258
|
+
fromChainId,
|
|
259
|
+
toTokenAddress,
|
|
260
|
+
toChainId,
|
|
261
|
+
estUsdValue: Number(estUsdValue) || 0,
|
|
262
|
+
clientId
|
|
263
|
+
});
|
|
264
|
+
const appFeeBp = feeInfo.b + feeInfo.v;
|
|
231
265
|
logger.info("getRelayQuoteParams", {
|
|
232
266
|
...params,
|
|
233
267
|
tokenAmountBaseUnit,
|
|
234
|
-
txs
|
|
268
|
+
txs,
|
|
269
|
+
priceInfo,
|
|
270
|
+
feeInfo,
|
|
271
|
+
appFeeBp
|
|
235
272
|
});
|
|
236
273
|
const relayQuote = await relayClient.actions.getQuote({
|
|
237
274
|
chainId: Number(fromChainId),
|
|
@@ -244,12 +281,10 @@ async function getRelayQuote({
|
|
|
244
281
|
user: userAddress,
|
|
245
282
|
...txs && { txs },
|
|
246
283
|
options: {
|
|
247
|
-
referrer: FUN_RELAY_REFERRER,
|
|
284
|
+
referrer: clientId ? `${FUN_RELAY_REFERRER}|${clientId}` : FUN_RELAY_REFERRER,
|
|
248
285
|
appFees: [
|
|
249
286
|
{
|
|
250
|
-
fee:
|
|
251
|
-
isSameToken: fromChainId === toChainId && fromTokenAddress.toLowerCase() === toTokenAddress.toLowerCase()
|
|
252
|
-
}).toString(),
|
|
287
|
+
fee: appFeeBp.toString(),
|
|
253
288
|
recipient: FUN_RELAY_REVENUE_WALLET
|
|
254
289
|
}
|
|
255
290
|
],
|
|
@@ -315,7 +350,6 @@ export {
|
|
|
315
350
|
FUN_RELAY_REVENUE_WALLET,
|
|
316
351
|
LogLevel,
|
|
317
352
|
RELAY_TERMINAL_STATUSES,
|
|
318
|
-
computeFunRelayFeeBps,
|
|
319
353
|
convertFunToRelayTokenAddress,
|
|
320
354
|
executeRelayQuote,
|
|
321
355
|
getRelayAssetPriceInfo,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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 = 3_000 // 3 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 function computeFunRelayFeeBps({\n isSameToken,\n}: {\n isSameToken: boolean\n}): number {\n // For now, we have a flat 2bps app fee for all relay transactions\n // TODO: Dynamic fee based on the transaction size, from token, to token, etc\n return isSameToken ? 0 : 2\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 { computeFunRelayFeeBps, 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} & (\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 } = params\n\n try {\n const relayClient = getRelayClient()\n\n const tokenAmountBaseUnit =\n params.tradeType === 'EXACT_INPUT'\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 logger.info('getRelayQuoteParams', {\n ...params,\n tokenAmountBaseUnit,\n txs,\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: FUN_RELAY_REFERRER,\n appFees: [\n {\n fee: computeFunRelayFeeBps({\n isSameToken:\n fromChainId === toChainId &&\n fromTokenAddress.toLowerCase() === toTokenAddress.toLowerCase(),\n }).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": ";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;;;
|
|
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
6
|
"names": ["MAINNET_RELAY_API", "MAINNET_RELAY_API", "MAINNET_RELAY_API"]
|
|
7
7
|
}
|
package/dist/src/constants.d.ts
CHANGED
|
@@ -18,6 +18,6 @@ export declare const FUN_RELAY_REFERRER = "funxyz";
|
|
|
18
18
|
/**
|
|
19
19
|
* Buffer added to Relay's time estimate (which sometimes is 0)
|
|
20
20
|
*/
|
|
21
|
-
export declare const RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS =
|
|
21
|
+
export declare const RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 25000;
|
|
22
22
|
export declare const RELAY_TERMINAL_STATUSES: RelayExecutionStatus[];
|
|
23
23
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C;;GAEG;AACH,eAAO,MAAM,mBAAmB,+CACgC,CAAA;AAEhE;;GAEG;AACH,eAAO,MAAM,kBAAkB,+CACiC,CAAA;AAEhE;;GAEG;AACH,eAAO,MAAM,wBAAwB,+CAC2B,CAAA;AAEhE;;GAEG;AACH,eAAO,MAAM,kBAAkB,WAAW,CAAA;AAE1C;;GAEG;AACH,eAAO,MAAM,mCAAmC,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C;;GAEG;AACH,eAAO,MAAM,mBAAmB,+CACgC,CAAA;AAEhE;;GAEG;AACH,eAAO,MAAM,kBAAkB,+CACiC,CAAA;AAEhE;;GAEG;AACH,eAAO,MAAM,wBAAwB,+CAC2B,CAAA;AAEhE;;GAEG;AACH,eAAO,MAAM,kBAAkB,WAAW,CAAA;AAE1C;;GAEG;AACH,eAAO,MAAM,mCAAmC,QAAS,CAAA;AAEzD,eAAO,MAAM,uBAAuB,EAAE,oBAAoB,EAIzD,CAAA"}
|
package/dist/src/fees.d.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import type { CallFees } from '@reservoir0x/relay-sdk';
|
|
2
2
|
import type { Logger } from './types';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export interface FunRelayFeeItem {
|
|
4
|
+
b: number;
|
|
5
|
+
v: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function getFunRelayFees({ fromTokenAddress, fromChainId, toTokenAddress, toChainId, estUsdValue, clientId, }: {
|
|
8
|
+
fromTokenAddress: string;
|
|
9
|
+
fromChainId: string;
|
|
10
|
+
toTokenAddress: string;
|
|
11
|
+
toChainId: string;
|
|
12
|
+
estUsdValue: number;
|
|
13
|
+
clientId: string;
|
|
14
|
+
}): Promise<FunRelayFeeItem>;
|
|
6
15
|
export declare function parseRelayFees({ fees, logger, }: {
|
|
7
16
|
fees: CallFees | undefined;
|
|
8
17
|
logger: Logger;
|
package/dist/src/fees.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fees.d.ts","sourceRoot":"","sources":["../../src/fees.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,
|
|
1
|
+
{"version":3,"file":"fees.d.ts","sourceRoot":"","sources":["../../src/fees.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,wBAAsB,eAAe,CAAC,EACpC,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,SAAS,EACT,WAAW,EACX,QAAQ,GACT,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;CACjB,GAAG,OAAO,CAAC,eAAe,CAAC,CAS3B;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf;;;;;;EAkDA"}
|
package/dist/src/quote.d.ts
CHANGED
package/dist/src/quote.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|