@funkit/fun-relay 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # @funkit/fun-relay
2
+
3
+ ## 0.1.0
4
+
5
+ In development
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @funkit/fun-relay
@@ -0,0 +1,6 @@
1
+ export { getRelayClient, initializeRelayClient, type InitializeRelayClientParams, } from './src/client';
2
+ export { type ExecuteRelayQuoteParams, executeRelayQuote, getRelayExecutionInfo, } from './src/execution';
3
+ export { type GetRelayQuoteParams, getRelayQuote } from './src/quote';
4
+ export { getRelayExecutionRefundState, getRelayExecutionState, isRelayExecutionTerminalStatus, } from './src/utils';
5
+ export { LogLevel, type RelayExecutionInfo, type RelayExecutionStatus, } from './src/types';
6
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,327 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ LogLevel: () => import_relay_sdk3.LogLevel,
24
+ executeRelayQuote: () => executeRelayQuote,
25
+ getRelayClient: () => getRelayClient,
26
+ getRelayExecutionInfo: () => getRelayExecutionInfo,
27
+ getRelayExecutionRefundState: () => getRelayExecutionRefundState,
28
+ getRelayExecutionState: () => getRelayExecutionState,
29
+ getRelayQuote: () => getRelayQuote,
30
+ initializeRelayClient: () => initializeRelayClient,
31
+ isRelayExecutionTerminalStatus: () => isRelayExecutionTerminalStatus
32
+ });
33
+ module.exports = __toCommonJS(index_exports);
34
+
35
+ // src/client.ts
36
+ var import_relay_sdk = require("@reservoir0x/relay-sdk");
37
+ function initializeRelayClient({
38
+ chains,
39
+ logger,
40
+ ...options
41
+ }) {
42
+ return (0, import_relay_sdk.createClient)({
43
+ ...options,
44
+ baseApiUrl: import_relay_sdk.MAINNET_RELAY_API,
45
+ chains: chains.map(import_relay_sdk.convertViemChainToRelayChain),
46
+ logger: (message) => {
47
+ logger.log("[RelayClient]:", message);
48
+ }
49
+ });
50
+ }
51
+ function getRelayClient() {
52
+ const client = (0, import_relay_sdk.getClient)();
53
+ if (!client) {
54
+ throw new Error("Relay client is not defined");
55
+ }
56
+ return client;
57
+ }
58
+
59
+ // src/execution.ts
60
+ var import_relay_sdk2 = require("@reservoir0x/relay-sdk");
61
+ async function executeRelayQuote({
62
+ logger,
63
+ onConfirmed,
64
+ onError,
65
+ relayQuote,
66
+ stepMessageSetter,
67
+ walletClient
68
+ }) {
69
+ await getRelayClient().actions.execute({
70
+ quote: relayQuote,
71
+ wallet: walletClient,
72
+ onProgress: async ({
73
+ steps,
74
+ fees,
75
+ breakdown,
76
+ currentStep,
77
+ currentStepItem,
78
+ txHashes,
79
+ details,
80
+ error
81
+ }) => {
82
+ const logPrefix = "onRelayProgress";
83
+ logger.log(`${logPrefix}:params`, {
84
+ steps,
85
+ currentStep,
86
+ fees,
87
+ breakdown,
88
+ currentStepItem,
89
+ txHashes,
90
+ details,
91
+ error
92
+ });
93
+ stepMessageSetter(currentStep?.action ?? "");
94
+ if (error) {
95
+ logger.log(`${logPrefix}:errorDetected`, error);
96
+ await onError(error).catch((e) => {
97
+ logger.error(`${logPrefix}:onErrorFailed`, e);
98
+ });
99
+ } else if (
100
+ // We can redirect as soon as all the required user steps are done
101
+ // https://fun-xyz.slack.com/archives/C08MQ85QB2N/p1748381169792379
102
+ txHashes && txHashes.length > 0 && txHashes.length === steps.length
103
+ ) {
104
+ logger.log(`${logPrefix}:completed`, txHashes);
105
+ await onConfirmed(txHashes[0].txHash).catch((e) => {
106
+ logger.error(`${logPrefix}:onConfirmedFailed`, e);
107
+ });
108
+ }
109
+ }
110
+ });
111
+ }
112
+ async function getRelayExecutionInfo(requestId) {
113
+ const url = `${import_relay_sdk2.MAINNET_RELAY_API}/intents/status/v2?requestId=${requestId}`;
114
+ const response = await fetch(url);
115
+ if (!response.ok) {
116
+ throw Error(response.statusText);
117
+ }
118
+ const data = await response.json();
119
+ return data;
120
+ }
121
+
122
+ // src/quote.ts
123
+ var import_viem = require("viem");
124
+
125
+ // src/constants.ts
126
+ var FUNKIT_NATIVE_TOKEN = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
127
+ var RELAY_NATIVE_TOKEN = "0x0000000000000000000000000000000000000000";
128
+ var FUN_RELAY_REVENUE_WALLET = "0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E";
129
+ var FUN_RELAY_REFERRER = "funxyz";
130
+ var RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 3e3;
131
+ var RELAY_TERMINAL_STATUSES = [
132
+ "refund",
133
+ "failure",
134
+ "success"
135
+ ];
136
+
137
+ // src/fees.ts
138
+ function computeFunRelayFeeBps({
139
+ isSameToken
140
+ }) {
141
+ return isSameToken ? 0 : 2;
142
+ }
143
+ function parseRelayFees({
144
+ fees,
145
+ logger
146
+ }) {
147
+ const relayGasFeesUsd = Number.parseFloat(fees?.gas?.amountUsd || "0");
148
+ const funLpFeesUsd = Number.parseFloat(fees?.app?.amountUsd || "0");
149
+ const funLpFeesFromAmount = Number.parseFloat(
150
+ fees?.app?.amountFormatted || "0"
151
+ );
152
+ const funLpFeesFromAmountBaseUnit = BigInt(fees?.app?.amount || "0");
153
+ const relayLpFeesUsd = Number.parseFloat(fees?.relayer?.amountUsd || "0") + Number.parseFloat(fees?.relayerGas?.amountUsd || "0") + Number.parseFloat(fees?.relayerService?.amountUsd || "0");
154
+ const relayLpFeesFromAmount = Number.parseFloat(fees?.relayer?.amountFormatted || "0") + Number.parseFloat(fees?.relayerGas?.amountFormatted || "0") + Number.parseFloat(fees?.relayerService?.amountFormatted || "0");
155
+ const relayLpFeesFromAmountBaseUnit = BigInt(fees?.relayer?.amount || "0") + BigInt(fees?.relayerGas?.amount || "0") + BigInt(fees?.relayerService?.amount || "0");
156
+ const totalLpFeesUsd = funLpFeesUsd + relayLpFeesUsd;
157
+ const totalLpFeesFromAmount = funLpFeesFromAmount + relayLpFeesFromAmount;
158
+ const totalLpFeesFromAmountBaseUnit = funLpFeesFromAmountBaseUnit + relayLpFeesFromAmountBaseUnit;
159
+ logger.log("parseRelayFees", {
160
+ relayGasFeesUsd,
161
+ funLpFeesUsd,
162
+ funLpFeesFromAmount,
163
+ funLpFeesFromAmountBaseUnit,
164
+ relayLpFeesUsd,
165
+ relayLpFeesFromAmount,
166
+ relayLpFeesFromAmountBaseUnit,
167
+ totalLpFeesUsd,
168
+ totalLpFeesFromAmount,
169
+ totalLpFeesFromAmountBaseUnit
170
+ });
171
+ return {
172
+ relayGasFeesUsd,
173
+ totalLpFeesUsd,
174
+ totalFeesUsd: relayGasFeesUsd + totalLpFeesUsd,
175
+ totalFeesFromAmount: totalLpFeesFromAmount,
176
+ totalFeesFromAmountBaseUnit: totalLpFeesFromAmountBaseUnit
177
+ };
178
+ }
179
+
180
+ // src/types.ts
181
+ var import_relay_sdk3 = require("@reservoir0x/relay-sdk");
182
+
183
+ // src/utils.ts
184
+ function convertFunToRelayTokenAddress(address) {
185
+ if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {
186
+ return RELAY_NATIVE_TOKEN;
187
+ }
188
+ return address;
189
+ }
190
+ function getRelayExecutionRefundState(info) {
191
+ switch (info.status) {
192
+ case "refund":
193
+ return "REFUNDED" /* REFUNDED */;
194
+ default:
195
+ return void 0;
196
+ }
197
+ }
198
+ function getRelayExecutionState(info) {
199
+ switch (info.status) {
200
+ case "success":
201
+ return "COMPLETED" /* COMPLETED */;
202
+ case "failure":
203
+ case "refund":
204
+ return "CHECKOUT_ERROR" /* CHECKOUT_ERROR */;
205
+ default:
206
+ return "PENDING_RECEIVAL" /* PENDING_RECEIVAL */;
207
+ }
208
+ }
209
+ function isRelayExecutionTerminalStatus(info) {
210
+ return RELAY_TERMINAL_STATUSES.includes(info.status);
211
+ }
212
+
213
+ // src/quote.ts
214
+ async function getRelayQuote({
215
+ actionParams,
216
+ logger,
217
+ toChainId,
218
+ toTokenAddress,
219
+ toTokenAmount,
220
+ toTokenDecimals,
221
+ fromChainId,
222
+ fromTokenAddress,
223
+ recipientAddress,
224
+ userAddress
225
+ }) {
226
+ try {
227
+ const relayClient = getRelayClient();
228
+ const toMultipler = 10 ** toTokenDecimals;
229
+ const toAmountBaseUnitBI = BigInt(Math.floor(toTokenAmount * toMultipler));
230
+ const toAmountBaseUnitBIString = toAmountBaseUnitBI.toString();
231
+ const txs = actionParams?.map((action) => {
232
+ const data = (0, import_viem.encodeFunctionData)({
233
+ abi: action.contractAbi,
234
+ args: action.functionArgs,
235
+ functionName: action.functionName
236
+ });
237
+ return {
238
+ data,
239
+ to: action.contractAddress,
240
+ value: String(action.value ?? 0n)
241
+ };
242
+ });
243
+ logger.log("getRelayQuoteParams", {
244
+ actionParams,
245
+ toChainId,
246
+ toTokenAddress,
247
+ toTokenAmount,
248
+ toTokenDecimals,
249
+ fromChainId,
250
+ fromTokenAddress,
251
+ recipientAddress,
252
+ userAddress,
253
+ relayClient,
254
+ toAmountBaseUnitBI: toAmountBaseUnitBIString,
255
+ txs
256
+ });
257
+ const relayQuote = await relayClient.actions.getQuote({
258
+ chainId: Number(fromChainId),
259
+ toChainId: Number(toChainId),
260
+ currency: convertFunToRelayTokenAddress(fromTokenAddress),
261
+ toCurrency: convertFunToRelayTokenAddress(toTokenAddress),
262
+ amount: toAmountBaseUnitBIString,
263
+ recipient: recipientAddress,
264
+ tradeType: "EXACT_OUTPUT",
265
+ user: userAddress,
266
+ ...txs && { txs },
267
+ options: {
268
+ referrer: FUN_RELAY_REFERRER,
269
+ appFees: [
270
+ {
271
+ fee: computeFunRelayFeeBps({
272
+ isSameToken: fromChainId === toChainId && fromTokenAddress.toLowerCase() === toTokenAddress.toLowerCase()
273
+ }).toString(),
274
+ recipient: FUN_RELAY_REVENUE_WALLET
275
+ }
276
+ ]
277
+ }
278
+ });
279
+ logger.log("relayQuote", relayQuote);
280
+ const estSubtotalUsd = Number(
281
+ relayQuote.details?.currencyOut?.amountUsd || 0
282
+ );
283
+ const estTotalUsd = Number(relayQuote.details?.currencyIn?.amountUsd || 0);
284
+ const fromAmountString = relayQuote.details?.currencyIn?.amountFormatted || "0";
285
+ const fromAmountBaseUnitString = relayQuote.details?.currencyIn?.amount || "0";
286
+ const relayRequestId = relayQuote.steps[0]?.requestId;
287
+ if (!relayRequestId) {
288
+ throw new Error("Relay quote does not contain a requestId");
289
+ }
290
+ const {
291
+ relayGasFeesUsd,
292
+ totalLpFeesUsd,
293
+ totalFeesUsd,
294
+ totalFeesFromAmount,
295
+ totalFeesFromAmountBaseUnit
296
+ } = parseRelayFees({ fees: relayQuote.fees, logger });
297
+ const estSubtotalFromAmount = (Number.parseFloat(fromAmountString) - totalFeesFromAmount).toString();
298
+ const estSubtotalFromAmountBaseUnit = (BigInt(fromAmountBaseUnitString) - totalFeesFromAmountBaseUnit).toString();
299
+ return {
300
+ quoteId: relayRequestId,
301
+ estTotalFromAmount: fromAmountString,
302
+ estSubtotalFromAmount,
303
+ estTotalFromAmountBaseUnit: fromAmountBaseUnitString,
304
+ estSubtotalFromAmountBaseUnit,
305
+ estFeesFromAmount: totalFeesFromAmount.toString(),
306
+ estFeesFromAmountBaseUnit: totalFeesFromAmountBaseUnit.toString(),
307
+ fromTokenAddress,
308
+ estFeesUsd: totalFeesUsd,
309
+ estSubtotalUsd,
310
+ estTotalUsd,
311
+ estCheckoutTimeMs: (relayQuote.details?.timeEstimate || 0) * 1e3 + RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,
312
+ estMarketMakerGasUsd: relayGasFeesUsd,
313
+ lpFeePercentage: 0,
314
+ // TODO: ?
315
+ lpFeeUsd: totalLpFeesUsd,
316
+ metadata: {
317
+ relayQuote,
318
+ toAmountBaseUnit: toAmountBaseUnitBIString
319
+ }
320
+ };
321
+ } catch (err) {
322
+ throw new Error(
323
+ `An error occured trying to generate a relay quote: ${err instanceof Error ? err.message : JSON.stringify(err)}`
324
+ );
325
+ }
326
+ }
327
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../index.ts", "../src/client.ts", "../src/execution.ts", "../src/quote.ts", "../src/constants.ts", "../src/fees.ts", "../src/types.ts", "../src/utils.ts"],
4
+ "sourcesContent": ["export {\n getRelayClient,\n initializeRelayClient,\n type InitializeRelayClientParams,\n} from './src/client'\nexport {\n type ExecuteRelayQuoteParams,\n executeRelayQuote,\n getRelayExecutionInfo,\n} from './src/execution'\nexport { type GetRelayQuoteParams, getRelayQuote } from './src/quote'\nexport {\n getRelayExecutionRefundState,\n getRelayExecutionState,\n isRelayExecutionTerminalStatus,\n} from './src/utils'\nexport {\n LogLevel,\n type RelayExecutionInfo,\n type RelayExecutionStatus,\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.log('[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 { type Execute, MAINNET_RELAY_API } from '@reservoir0x/relay-sdk'\nimport type { Hex, WalletClient } from 'viem'\nimport { getRelayClient } from './client'\nimport type { Logger, RelayExecutionInfo } from './types'\n\nexport interface ExecuteRelayQuoteParams {\n logger: Logger\n onConfirmed: (txHash: Hex) => Promise<void>\n onError: (error: Error) => Promise<void>\n relayQuote: Execute\n stepMessageSetter: (message: string) => void\n walletClient: WalletClient\n}\n\n// TODO: Add unit tests for this once impl is settled\nexport async function executeRelayQuote({\n logger,\n onConfirmed,\n onError,\n relayQuote,\n stepMessageSetter,\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.log(`${logPrefix}:params`, {\n steps,\n currentStep,\n fees,\n breakdown,\n currentStepItem,\n txHashes,\n details,\n error,\n })\n\n stepMessageSetter(currentStep?.action ?? '')\n\n if (error) {\n logger.log(`${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.log(`${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 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\nexport interface GetRelayQuoteParams {\n actionParams?: ApiFunkitCheckoutActionParams[]\n fromChainId: string\n fromTokenAddress: Address\n logger: Logger\n recipientAddress: Address | undefined\n toChainId: string\n toTokenAddress: Address\n toTokenAmount: number\n toTokenDecimals: number\n userAddress: Address | undefined\n}\n\nexport async function getRelayQuote({\n actionParams,\n logger,\n toChainId,\n toTokenAddress,\n toTokenAmount,\n toTokenDecimals,\n fromChainId,\n fromTokenAddress,\n recipientAddress,\n userAddress,\n}: GetRelayQuoteParams): Promise<CheckoutQuoteResponse> {\n try {\n const relayClient = getRelayClient()\n\n // Mirror logic in api-base (this is wrong)\n const toMultipler = 10 ** toTokenDecimals\n const toAmountBaseUnitBI = BigInt(Math.floor(toTokenAmount * toMultipler))\n const toAmountBaseUnitBIString = toAmountBaseUnitBI.toString()\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.log('getRelayQuoteParams', {\n actionParams,\n toChainId,\n toTokenAddress,\n toTokenAmount,\n toTokenDecimals,\n fromChainId,\n fromTokenAddress,\n recipientAddress,\n userAddress,\n relayClient,\n toAmountBaseUnitBI: toAmountBaseUnitBIString,\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: toAmountBaseUnitBIString,\n recipient: recipientAddress,\n tradeType: 'EXACT_OUTPUT',\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 },\n })\n\n // TODO: Handling for no route response\n\n logger.log('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 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 estTotalFromAmount: fromAmountString,\n estSubtotalFromAmount,\n estTotalFromAmountBaseUnit: fromAmountBaseUnitString,\n estSubtotalFromAmountBaseUnit: estSubtotalFromAmountBaseUnit,\n estFeesFromAmount: totalFeesFromAmount.toString(),\n estFeesFromAmountBaseUnit: totalFeesFromAmountBaseUnit.toString(),\n fromTokenAddress,\n estFeesUsd: totalFeesUsd,\n estSubtotalUsd,\n estTotalUsd,\n estCheckoutTimeMs:\n (relayQuote.details?.timeEstimate || 0) * 1000 +\n RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS,\n estMarketMakerGasUsd: relayGasFeesUsd,\n lpFeePercentage: 0, // TODO: ?\n lpFeeUsd: totalLpFeesUsd,\n metadata: {\n relayQuote,\n toAmountBaseUnit: toAmountBaseUnitBIString,\n },\n }\n } catch (err) {\n throw new Error(\n `An error occured 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 type { 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 'refund',\n 'failure',\n 'success',\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.log('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 { LogLevel } from '@reservoir0x/relay-sdk'\nimport type { Abi, Address } from 'viem'\n\nexport { LogLevel }\n\nexport type RelayExecutionStatus =\n | 'refund'\n | 'delayed'\n | 'waiting'\n | 'failure'\n | 'pending'\n | 'success'\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//// 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 log(message: string, data?: object): void\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 {\n FUNKIT_NATIVE_TOKEN,\n RELAY_NATIVE_TOKEN,\n RELAY_TERMINAL_STATUSES,\n} from './constants'\nimport {\n CheckoutRefundState,\n CheckoutState,\n type RelayExecutionInfo,\n} from './types'\n\n/**\n * Converts a token address within Funkit the corresponding Relay token address.\n */\nexport function convertFunToRelayTokenAddress(address: Address): Address {\n if (address.toLowerCase() === FUNKIT_NATIVE_TOKEN.toLowerCase()) {\n return RELAY_NATIVE_TOKEN\n }\n\n return address\n}\n\nexport function getRelayExecutionRefundState(\n info: RelayExecutionInfo,\n): CheckoutRefundState | undefined {\n switch (info.status) {\n case 'refund':\n return CheckoutRefundState.REFUNDED\n default:\n return undefined\n }\n}\n\nexport function getRelayExecutionState(\n info: RelayExecutionInfo,\n): CheckoutState {\n switch (info.status) {\n case 'success':\n return CheckoutState.COMPLETED\n case 'failure':\n case 'refund':\n return CheckoutState.CHECKOUT_ERROR\n default:\n return CheckoutState.PENDING_RECEIVAL\n }\n}\n\n/**\n * Checks whether the Relay execution has reached a terminal status.\n */\nexport function isRelayExecutionTerminalStatus(\n info: RelayExecutionInfo,\n): boolean {\n return RELAY_TERMINAL_STATUSES.includes(info.status)\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_relay_sdk", "import_relay_sdk"]
7
+ }
@@ -0,0 +1,17 @@
1
+ import { type RelayClient, type RelayClientOptions } from '@reservoir0x/relay-sdk';
2
+ import type { Chain } from 'viem';
3
+ import type { Logger } from './types';
4
+ export type InitializeRelayClientParams = Omit<RelayClientOptions, 'baseApiUrl' | 'chains' | 'logger'> & {
5
+ chains: Chain[];
6
+ logger: Logger;
7
+ };
8
+ /**
9
+ * Initializes a global instance of the RelayClient
10
+ * https://docs.relay.link/references/sdk/createClient
11
+ */
12
+ export declare function initializeRelayClient({ chains, logger, ...options }: InitializeRelayClientParams): RelayClient;
13
+ /**
14
+ * Gets the global instance of the RelayClient
15
+ */
16
+ export declare function getRelayClient(): RelayClient;
17
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,kBAAkB,EAIxB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,MAAM,CAAA;AACjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,kBAAkB,EAClB,YAAY,GAAG,QAAQ,GAAG,QAAQ,CACnC,GAAG;IACF,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,MAAM,EACN,GAAG,OAAO,EACX,EAAE,2BAA2B,GAAG,WAAW,CAS3C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAQ5C"}
@@ -0,0 +1,23 @@
1
+ import type { RelayExecutionStatus } from './types';
2
+ /**
3
+ * Fake address for a chain's native currency used by Funkit
4
+ */
5
+ export declare const FUNKIT_NATIVE_TOKEN = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
6
+ /**
7
+ * Fake address for a chain's native currency used by Relay
8
+ */
9
+ export declare const RELAY_NATIVE_TOKEN = "0x0000000000000000000000000000000000000000";
10
+ /**
11
+ * Wallet that receives the app fees collected by Relay
12
+ */
13
+ export declare const FUN_RELAY_REVENUE_WALLET = "0xb61562d83aEC43a050A06BED12Ac2bD8f9BFfd5E";
14
+ /**
15
+ * Referred field in Relay quote
16
+ */
17
+ export declare const FUN_RELAY_REFERRER = "funxyz";
18
+ /**
19
+ * Buffer added to Relay's time estimate (which sometimes is 0)
20
+ */
21
+ export declare const RELAY_QUOTE_CHECKOUT_TIME_BUFFER_MS = 3000;
22
+ export declare const RELAY_TERMINAL_STATUSES: RelayExecutionStatus[];
23
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD;;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,OAAQ,CAAA;AAExD,eAAO,MAAM,uBAAuB,EAAE,oBAAoB,EAIzD,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { type Execute } from '@reservoir0x/relay-sdk';
2
+ import type { Hex, WalletClient } from 'viem';
3
+ import type { Logger, RelayExecutionInfo } from './types';
4
+ export interface ExecuteRelayQuoteParams {
5
+ logger: Logger;
6
+ onConfirmed: (txHash: Hex) => Promise<void>;
7
+ onError: (error: Error) => Promise<void>;
8
+ relayQuote: Execute;
9
+ stepMessageSetter: (message: string) => void;
10
+ walletClient: WalletClient;
11
+ }
12
+ export declare function executeRelayQuote({ logger, onConfirmed, onError, relayQuote, stepMessageSetter, walletClient, }: ExecuteRelayQuoteParams): Promise<void>;
13
+ export declare function getRelayExecutionInfo(requestId: string): Promise<RelayExecutionInfo>;
14
+ //# sourceMappingURL=execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../src/execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAqB,MAAM,wBAAwB,CAAA;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEzD,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,UAAU,EAAE,OAAO,CAAA;IACnB,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,YAAY,EAAE,YAAY,CAAA;CAC3B;AAGD,wBAAsB,iBAAiB,CAAC,EACtC,MAAM,EACN,WAAW,EACX,OAAO,EACP,UAAU,EACV,iBAAiB,EACjB,YAAY,GACb,EAAE,uBAAuB,iBAiDzB;AAED,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAS7B"}
@@ -0,0 +1,16 @@
1
+ import type { CallFees } from '@reservoir0x/relay-sdk';
2
+ import type { Logger } from './types';
3
+ export declare function computeFunRelayFeeBps({ isSameToken, }: {
4
+ isSameToken: boolean;
5
+ }): number;
6
+ export declare function parseRelayFees({ fees, logger, }: {
7
+ fees: CallFees | undefined;
8
+ logger: Logger;
9
+ }): {
10
+ relayGasFeesUsd: number;
11
+ totalLpFeesUsd: number;
12
+ totalFeesUsd: number;
13
+ totalFeesFromAmount: number;
14
+ totalFeesFromAmountBaseUnit: bigint;
15
+ };
16
+ //# sourceMappingURL=fees.d.ts.map
@@ -0,0 +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,wBAAgB,qBAAqB,CAAC,EACpC,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,OAAO,CAAA;CACrB,GAAG,MAAM,CAIT;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf;;;;;;EAkDA"}
@@ -0,0 +1,16 @@
1
+ import { type Address } from 'viem';
2
+ import type { ApiFunkitCheckoutActionParams, CheckoutQuoteResponse, Logger } from './types';
3
+ export interface GetRelayQuoteParams {
4
+ actionParams?: ApiFunkitCheckoutActionParams[];
5
+ fromChainId: string;
6
+ fromTokenAddress: Address;
7
+ logger: Logger;
8
+ recipientAddress: Address | undefined;
9
+ toChainId: string;
10
+ toTokenAddress: Address;
11
+ toTokenAmount: number;
12
+ toTokenDecimals: number;
13
+ userAddress: Address | undefined;
14
+ }
15
+ export declare function getRelayQuote({ actionParams, logger, toChainId, toTokenAddress, toTokenAmount, toTokenDecimals, fromChainId, fromTokenAddress, recipientAddress, userAddress, }: GetRelayQuoteParams): Promise<CheckoutQuoteResponse>;
16
+ //# sourceMappingURL=quote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../src/quote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,MAAM,CAAA;AAQvD,OAAO,KAAK,EACV,6BAA6B,EAC7B,qBAAqB,EACrB,MAAM,EACP,MAAM,SAAS,CAAA;AAGhB,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,6BAA6B,EAAE,CAAA;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,OAAO,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,OAAO,GAAG,SAAS,CAAA;CACjC;AAED,wBAAsB,aAAa,CAAC,EAClC,YAAY,EACZ,MAAM,EACN,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,GACZ,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAqItD"}
@@ -0,0 +1,72 @@
1
+ import { LogLevel } from '@reservoir0x/relay-sdk';
2
+ import type { Abi, Address } from 'viem';
3
+ export { LogLevel };
4
+ export type RelayExecutionStatus = 'refund' | 'delayed' | 'waiting' | 'failure' | 'pending' | 'success';
5
+ export interface RelayExecutionInfo {
6
+ status: RelayExecutionStatus;
7
+ details: string;
8
+ /** Incoming transaction hashes */
9
+ inTxHashes: string[];
10
+ /** Outgoing transaction hashes */
11
+ txHashes: string[];
12
+ /** The last timestamp the data was updated in milliseconds */
13
+ time: number;
14
+ originChainId: number;
15
+ destinationChainId: number;
16
+ }
17
+ export interface Logger {
18
+ error(message: string, data?: object): void;
19
+ log(message: string, data?: object): void;
20
+ }
21
+ export interface ApiFunkitCheckoutActionParams {
22
+ contractAbi: Abi;
23
+ contractAddress: Address;
24
+ functionName: string;
25
+ functionArgs: unknown[];
26
+ value?: bigint;
27
+ }
28
+ export declare enum CheckoutRefundState {
29
+ INITIATED = "INITIATED",
30
+ ERROR = "ERROR",
31
+ REFUNDED = "REFUNDED",
32
+ PROCEEDED = "PROCEEDED",
33
+ WAITING_FOR_FULFILLMENT = "WAITING_FOR_FULFILLMENT",
34
+ FULFILLED = "FULFILLED"
35
+ }
36
+ export declare enum CheckoutState {
37
+ FROM_UNFUNDED = "FROM_UNFUNDED",
38
+ FROM_FUNDED = "FROM_FUNDED",
39
+ FROM_POOLED = "FROM_POOLED",
40
+ TO_UNFUNDED = "TO_UNFUNDED",
41
+ TO_FUNDED = "TO_FUNDED",
42
+ TO_POOLED = "TO_POOLED",
43
+ TO_READY = "TO_READY",
44
+ PENDING_RECEIVAL = "PENDING_RECEIVAL",
45
+ COMPLETED = "COMPLETED",
46
+ CHECKOUT_ERROR = "CHECKOUT_ERROR",
47
+ EXPIRED = "EXPIRED",
48
+ CANCELLED = "CANCELLED"
49
+ }
50
+ export type CheckoutApiQuoteResponse = {
51
+ quoteId: string;
52
+ estTotalFromAmountBaseUnit: string;
53
+ estSubtotalFromAmountBaseUnit: string;
54
+ estFeesFromAmountBaseUnit: string;
55
+ fromTokenAddress: Address;
56
+ estFeesUsd: number;
57
+ estSubtotalUsd: number;
58
+ estTotalUsd: number;
59
+ estCheckoutTimeMs: number;
60
+ estMarketMakerGasUsd: number;
61
+ lpFeePercentage: number;
62
+ lpFeeUsd: number;
63
+ };
64
+ export type CheckoutQuoteResponse = CheckoutApiQuoteResponse & {
65
+ estTotalFromAmount: string;
66
+ estSubtotalFromAmount: string;
67
+ estFeesFromAmount: string;
68
+ metadata?: {
69
+ [key: string]: unknown;
70
+ };
71
+ };
72
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAExC,OAAO,EAAE,QAAQ,EAAE,CAAA;AAEnB,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAA;AAGb,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,oBAAoB,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,kCAAkC;IAClC,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,kBAAkB,EAAE,MAAM,CAAA;CAC3B;AAMD,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3C,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1C;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,EAAE,GAAG,CAAA;IAChB,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,OAAO,EAAE,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,oBAAY,mBAAmB;IAC7B,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,uBAAuB,4BAA4B;IACnD,SAAS,cAAc;CACxB;AAGD,oBAAY,aAAa;IAEvB,aAAa,kBAAkB;IAC/B,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,SAAS,cAAc;IACvB,SAAS,cAAc;IACvB,QAAQ,aAAa;IACrB,gBAAgB,qBAAqB;IAErC,SAAS,cAAc;IACvB,cAAc,mBAAmB;IACjC,OAAO,YAAY;IACnB,SAAS,cAAc;CACxB;AAGD,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,0BAA0B,EAAE,MAAM,CAAA;IAClC,6BAA6B,EAAE,MAAM,CAAA;IACrC,yBAAyB,EAAE,MAAM,CAAA;IACjC,gBAAgB,EAAE,OAAO,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAGD,MAAM,MAAM,qBAAqB,GAAG,wBAAwB,GAAG;IAC7D,kBAAkB,EAAE,MAAM,CAAA;IAC1B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;IAGzB,QAAQ,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CACtC,CAAA"}
@@ -0,0 +1,13 @@
1
+ import type { Address } from 'viem';
2
+ import { CheckoutRefundState, CheckoutState, type RelayExecutionInfo } from './types';
3
+ /**
4
+ * Converts a token address within Funkit the corresponding Relay token address.
5
+ */
6
+ export declare function convertFunToRelayTokenAddress(address: Address): Address;
7
+ export declare function getRelayExecutionRefundState(info: RelayExecutionInfo): CheckoutRefundState | undefined;
8
+ export declare function getRelayExecutionState(info: RelayExecutionInfo): CheckoutState;
9
+ /**
10
+ * Checks whether the Relay execution has reached a terminal status.
11
+ */
12
+ export declare function isRelayExecutionTerminalStatus(info: RelayExecutionInfo): boolean;
13
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAMnC,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,KAAK,kBAAkB,EACxB,MAAM,SAAS,CAAA;AAEhB;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAMvE;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,kBAAkB,GACvB,mBAAmB,GAAG,SAAS,CAOjC;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,kBAAkB,GACvB,aAAa,CAUf;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAET"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@funkit/fun-relay",
3
+ "version": "0.1.0",
4
+ "files": [
5
+ "dist/src",
6
+ "dist/index.d.ts",
7
+ "dist/index.js",
8
+ "dist/index.js.map",
9
+ "CHANGELOG.md"
10
+ ],
11
+ "main": "./dist/index.js",
12
+ "module": "./dist/index.mjs",
13
+ "types": "./dist/index.d.ts",
14
+ "sideEffects": false,
15
+ "engines": {
16
+ "node": ">=18"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "dependencies": {
22
+ "@reservoir0x/relay-sdk": "^2.0.3"
23
+ },
24
+ "devDependencies": {
25
+ "viem": "^2.29.4"
26
+ },
27
+ "peerDependencies": {
28
+ "viem": ">=2.23.1"
29
+ },
30
+ "keywords": [
31
+ "blockchain",
32
+ "funkit"
33
+ ],
34
+ "author": "https://fun.xyz/",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/fun-xyz/funkit.git",
38
+ "directory": "packages/fun-relay"
39
+ },
40
+ "homepage": "https://github.com/fun-xyz/funkit/tree/main/packages/fun-relay",
41
+ "scripts": {
42
+ "build": "rm -rf dist && pnpm typegen && node build.mjs",
43
+ "build:watch": "rm -rf dist && node build.js --watch",
44
+ "lint": "biome check",
45
+ "lint:fix": "biome check --fix",
46
+ "test": "vitest",
47
+ "typecheck": "tsc --noEmit",
48
+ "typegen": "tsc --emitDeclarationOnly"
49
+ }
50
+ }