diff --git a/package-lock.json b/package-lock.json
index 62ea916f8..0d3f88d5d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,7 +16,7 @@
"@ledgerhq/hw-transport": "6.27.1",
"@ledgerhq/hw-transport-webhid": "6.27.1",
"@ledgerhq/logs": "6.12.0",
- "@mayanfinance/swap-sdk": "11.0.1",
+ "@mayanfinance/swap-sdk": "11.1.0",
"@metaplex-foundation/mpl-token-metadata": "3.4.0",
"@metaplex-foundation/umi": "0.9.2",
"@metaplex-foundation/umi-bundle-defaults": "0.9.2",
@@ -5426,18 +5426,18 @@
}
},
"node_modules/@mayanfinance/swap-sdk": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/@mayanfinance/swap-sdk/-/swap-sdk-11.0.1.tgz",
- "integrity": "sha512-DfD+Hw3ONdzqCrbKx7260C4y6A+LwfneT840yqxdXIqYejgnoJJphTm+j8VPVErZ92VL8PSZoZToVvB5a88jKA==",
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/@mayanfinance/swap-sdk/-/swap-sdk-11.1.0.tgz",
+ "integrity": "sha512-VaDnn4/5SbP5ZcVdEckVfWoGaiMQHFutVj+THseYPOKqlytIWqzBlNXUjx4w3Iv6GdaFvEfTHLb5w5MVvC1l1Q==",
"license": "MIT",
"dependencies": {
"@mysten/sui": "^1.34.0",
+ "@noble/hashes": "1.8.0",
"@solana/buffer-layout": "^4 || ^3",
"@solana/web3.js": "^1.87.6",
"bs58": "^6.0.0",
"cross-fetch": "^3.1.5",
"ethers": "^6",
- "js-sha256": "^0.9.0",
"js-sha3": "^0.8.0"
}
},
diff --git a/package.json b/package.json
index 4c3f51ff2..bc618a176 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,7 @@
"@ledgerhq/hw-transport": "6.27.1",
"@ledgerhq/hw-transport-webhid": "6.27.1",
"@ledgerhq/logs": "6.12.0",
- "@mayanfinance/swap-sdk": "11.0.1",
+ "@mayanfinance/swap-sdk": "11.1.0",
"@metaplex-foundation/mpl-token-metadata": "3.4.0",
"@metaplex-foundation/umi": "0.9.2",
"@metaplex-foundation/umi-bundle-defaults": "0.9.2",
diff --git a/src/components/SampleApp/index.tsx b/src/components/SampleApp/index.tsx
index e2ad84926..c93e5a846 100644
--- a/src/components/SampleApp/index.tsx
+++ b/src/components/SampleApp/index.tsx
@@ -37,6 +37,7 @@ import {
MayanRouteMCTP,
MayanRouteSWIFT,
MayanRouteMONOCHAIN,
+ MayanRouteFastMCTP,
} from '../../routes/mayan';
import { NTT_TEST_CONFIG_TESTNET, NTT_TEST_CONFIG_MAINNET } from './consts';
import { DEFAULT_ROUTES } from 'routes/operator';
@@ -77,6 +78,8 @@ const parseConfig = (config: string): WormholeConnectConfig => {
/* @ts-ignore */
window.MayanRouteMCTP = MayanRouteMCTP;
/* @ts-ignore */
+ window.MayanRouteFastMCTP = MayanRouteFastMCTP;
+ /* @ts-ignore */
window.MayanRouteMONOCHAIN = MayanRouteMONOCHAIN;
/* @ts-ignore */
window.MayanRouteSWIFT = MayanRouteSWIFT;
@@ -285,6 +288,10 @@ function SampleApp() {
MayanRouteSWIFT
{'RouteConstructor'}
+
+ MayanRouteFastMCTP
+ {'RouteConstructor'}
+
MayanRouteMONOCHAIN
{'RouteConstructor'}
diff --git a/src/exports/mayan.ts b/src/exports/mayan.ts
index 9b6f456a9..d93b824de 100644
--- a/src/exports/mayan.ts
+++ b/src/exports/mayan.ts
@@ -2,7 +2,8 @@ export {
MayanRoute,
MayanRouteWH,
MayanRouteMCTP,
+ MayanRouteFastMCTP,
MayanRouteSWIFT,
MayanRouteMONOCHAIN,
- createMayanRouteWithReferrerFee,
+ type ReferrerParams,
} from '../routes/mayan';
diff --git a/src/routes/mayan/MayanRoute.ts b/src/routes/mayan/MayanRoute.ts
new file mode 100644
index 000000000..291fde73a
--- /dev/null
+++ b/src/routes/mayan/MayanRoute.ts
@@ -0,0 +1,22 @@
+import type { Network } from '@wormhole-foundation/sdk-base';
+import type { routes } from '@wormhole-foundation/sdk-connect';
+import { MayanRouteBase } from './MayanRouteBase';
+import { MayanProtocol } from './types';
+
+export class MayanRoute
+ extends MayanRouteBase
+ implements routes.StaticRouteMethods
+{
+ static meta = {
+ name: 'MayanSwap',
+ provider: 'Mayan',
+ };
+
+ override protocols: MayanProtocol[] = [
+ MayanProtocol.WH,
+ MayanProtocol.MCTP,
+ MayanProtocol.FAST_MCTP,
+ MayanProtocol.SWIFT,
+ MayanProtocol.MONO_CHAIN,
+ ];
+}
diff --git a/src/routes/mayan/MayanRouteBase.ts b/src/routes/mayan/MayanRouteBase.ts
index fcbd99072..d34ba0501 100644
--- a/src/routes/mayan/MayanRouteBase.ts
+++ b/src/routes/mayan/MayanRouteBase.ts
@@ -1,8 +1,8 @@
import type {
ComposableSuiMoveCallsOptions,
Quote as MayanQuote,
+ QuoteOptions,
QuoteParams,
- ReferrerAddresses,
} from '@mayanfinance/swap-sdk';
import {
createSwapFromSolanaInstructions,
@@ -14,7 +14,7 @@ import type { SuiClient } from '@mysten/sui/client';
import { Transaction } from '@mysten/sui/transactions';
import {
createAssociatedTokenAccountIdempotentInstruction,
- createTransferInstruction,
+ createTransferCheckedInstruction,
getAssociatedTokenAddressSync,
} from '@solana/spl-token';
import type { Connection, TransactionInstruction } from '@solana/web3.js';
@@ -30,7 +30,7 @@ import {
generateFetchQuoteUrl as generateFetchQuoteUrlTestnet,
getSwapFromEvmTxPayload as getSwapFromEvmTxPayloadTestnet,
} from '@testnet-mayan/swap-sdk';
-import { chainToPlatform, circle } from '@wormhole-foundation/sdk-base';
+import { circle } from '@wormhole-foundation/sdk-base';
import type {
Chain,
ChainAddress,
@@ -82,62 +82,36 @@ import {
toMayanChainName,
txStatusToReceipt,
} from './utils';
-
-// eslint-disable-next-line @typescript-eslint/no-namespace
-export namespace MayanRoute {
- export type Options = {
- gasDrop: number;
- slippageBps: number | 'auto';
- optimizeFor: 'cost' | 'speed';
- };
- export type NormalizedParams = {
- slippageBps: number | 'auto';
- };
- export interface ValidatedParams
- extends routes.ValidatedTransferParams {
- normalizedParams: NormalizedParams;
- }
-}
-
-type Op = MayanRoute.Options;
-type Vp = MayanRoute.ValidatedParams;
-type Q = routes.Quote;
-type QR = routes.QuoteResult;
-type R = routes.Receipt;
-
-type Tp = routes.TransferParams;
-type Vr = routes.ValidationResult;
-
-type MayanProtocol =
- | 'WH'
- | 'MCTP'
- | 'SWIFT'
- | 'FAST_MCTP'
- | 'SHUTTLE'
- | 'MONO_CHAIN';
-
-type ReferrerParams = {
- getReferrerBps?: (request: routes.RouteTransferRequest) => number;
- referrers?: Partial>;
-
- // For temp feature flagging only
- isNewSolanaReferralEnabled?: boolean; // To be removed eventually
- isNewSuiReferralEnabled?: boolean; // To be removed eventually
- isNewEvmReferralEnabled?: boolean; // To be removed eventually
-};
-
-class MayanRouteBase extends routes.AutomaticRoute<
+import {
+ MayanProtocol,
+ type Options,
+ type Quote,
+ type QuoteResult,
+ type Receipt,
+ type ReferrerParams,
+ type TransferParams,
+ type ValidatedParams,
+ type ValidationResult,
+} from './types';
+
+export class MayanRouteBase extends routes.AutomaticRoute<
N,
- Op,
- Vp,
- R
+ Options,
+ ValidatedParams,
+ Receipt
> {
MAX_SLIPPAGE = 1;
static NATIVE_GAS_DROPOFF_SUPPORTED = false;
static override IS_AUTOMATIC = true;
- protocols: MayanProtocol[] = ['WH', 'MCTP', 'SWIFT', 'MONO_CHAIN'];
+ protocols: MayanProtocol[] = [
+ MayanProtocol.WH,
+ MayanProtocol.MCTP,
+ MayanProtocol.FAST_MCTP,
+ MayanProtocol.SWIFT,
+ MayanProtocol.MONO_CHAIN,
+ ];
protected isTestnetRequest(request: routes.RouteTransferRequest): boolean {
// A request is considered testnet if either the source or destination chain is on testnet
@@ -154,7 +128,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
return testnetCompatibleQuote;
}
- getDefaultOptions(): Op {
+ getDefaultOptions(): Options {
return {
gasDrop: 0,
slippageBps: 'auto',
@@ -193,8 +167,8 @@ class MayanRouteBase extends routes.AutomaticRoute<
async validate(
request: routes.RouteTransferRequest,
- params: Tp,
- ): Promise {
+ params: TransferParams,
+ ): Promise {
try {
params.options = params.options ?? this.getDefaultOptions();
@@ -206,7 +180,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
slippageBps: params.options.slippageBps,
},
},
- } as Vr;
+ } as ValidationResult;
} catch (e) {
return { valid: false, params, error: e as Error };
}
@@ -218,45 +192,15 @@ class MayanRouteBase extends routes.AutomaticRoute<
: getNativeContractAddress(tokenId.chain);
}
- // TODO remove function
- // Temp for feature flagging purposes
- isNewReferralEnabled(request: routes.RouteTransferRequest) {
- const referralParams = this.getReferralParameters(request);
-
- const {
- isNewSolanaReferralEnabled,
- isNewEvmReferralEnabled,
- isNewSuiReferralEnabled,
- } = referralParams;
-
- const { fromChain } = request;
- const isSolana = fromChain.chain === 'Solana';
- const isSui = fromChain.chain === 'Sui';
- const isEvm = !isSolana && !isSui;
-
- if (isSolana) {
- return !!isNewSolanaReferralEnabled;
- }
-
- if (isSui) {
- return !!isNewSuiReferralEnabled;
- }
-
- if (isEvm) {
- return !!isNewEvmReferralEnabled;
- }
-
- return false;
- }
-
getFeeInBaseUnits(
request: routes.RouteTransferRequest,
amountString: string,
) {
- const isNewReferralEnabled = this.isNewReferralEnabled(request);
- const { referrerBps, referrer } = this.getReferralParameters(request);
+ const { getReferrerBps } = this.constructor as ReferrerParams;
- if (!referrerBps || !referrer || !isNewReferralEnabled) {
+ const referrerBps = getReferrerBps ? getReferrerBps(request) : null;
+
+ if (!referrerBps) {
return 0n;
}
@@ -301,17 +245,10 @@ class MayanRouteBase extends routes.AutomaticRoute<
originalAmount: string,
) {
const { fromChain, source } = request;
- const referralParams = this.getReferralParameters(request);
- const { isNewSolanaReferralEnabled } = referralParams;
- const referrerAddress = this.referrerAddress()?.solana;
+ const referrerAddress = this.referrerAddress().solana;
const referralFee = this.getFeeInBaseUnits(request, originalAmount);
- if (
- !referrerAddress ||
- !referralFee ||
- fromChain.network !== 'Mainnet' ||
- !isNewSolanaReferralEnabled
- ) {
+ if (!referrerAddress || !referralFee || fromChain.network !== 'Mainnet') {
return instructionsFromMayanSwap;
}
@@ -364,11 +301,13 @@ class MayanRouteBase extends routes.AutomaticRoute<
}
instructions.push(
- createTransferInstruction(
+ createTransferCheckedInstruction(
senderAta,
+ mint,
referrerAta,
sender,
referralFee,
+ source.decimals,
undefined,
tokenProgramId,
),
@@ -387,21 +326,14 @@ class MayanRouteBase extends routes.AutomaticRoute<
originalAmount: string,
) {
const { fromChain, source } = request;
- const referralParams = this.getReferralParameters(request);
- const { isNewSuiReferralEnabled } = referralParams;
- const referrerAddress = this.referrerAddress()?.sui;
+ const referrerAddress = this.referrerAddress().sui;
const referralFee = this.getFeeInBaseUnits(request, originalAmount);
- const remainingAmount = this.getQuoteAmountIn64(request, originalAmount);
- if (
- !referrerAddress ||
- !referralFee ||
- fromChain.network !== 'Mainnet' ||
- !isNewSuiReferralEnabled
- ) {
+ if (!referrerAddress || !referralFee || fromChain.network !== 'Mainnet') {
return {};
}
+ const remainingAmount = this.getQuoteAmountIn64(request, originalAmount);
const tx = new Transaction();
const token = source.id.address;
const isSui = isNative(token);
@@ -444,7 +376,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
protected async fetchQuote(
request: routes.RouteTransferRequest,
- params: Vp,
+ params: ValidatedParams,
): Promise {
const { fromChain, toChain } = request;
@@ -482,19 +414,11 @@ class MayanRouteBase extends routes.AutomaticRoute<
slippageBps: 'auto',
};
- const referralParams = this.getReferralParameters(request);
- const isNewReferralEnabled = this.isNewReferralEnabled(request);
-
- // TODO remove this code once new referral code is ready
- if (!isNewReferralEnabled) {
- quoteParams.referrer = referralParams.referrer;
- quoteParams.referrerBps = referralParams.referrerBps;
- }
-
- const quoteOpts = {
- swift: this.protocols.includes('SWIFT'),
- mctp: this.protocols.includes('MCTP'),
- monoChain: this.protocols.includes('MONO_CHAIN'),
+ const quoteOpts: QuoteOptions = {
+ swift: this.protocols.includes(MayanProtocol.SWIFT),
+ mctp: this.protocols.includes(MayanProtocol.MCTP),
+ fastMctp: this.protocols.includes(MayanProtocol.FAST_MCTP),
+ monoChain: this.protocols.includes(MayanProtocol.MONO_CHAIN),
};
const fetchQuoteUrl = new URL(
@@ -526,7 +450,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
}
const quotes = res.data?.quotes?.filter((quote: MayanQuote) =>
- this.protocols.includes(quote.type),
+ this.protocols.includes(quote.type as MayanProtocol),
);
if (!quotes || quotes.length === 0) return undefined;
@@ -575,15 +499,15 @@ class MayanRouteBase extends routes.AutomaticRoute<
decimals,
);
return minAmount;
- } catch (e) {
+ } catch {
return null;
}
}
async quote(
request: routes.RouteTransferRequest,
- params: Vp,
- ): Promise {
+ params: ValidatedParams,
+ ): Promise {
try {
const quote = await this.fetchQuote(request, params);
if (!quote) {
@@ -616,7 +540,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
? new Date(deadline64Seconds)
: undefined;
- const fullQuote: Q = {
+ const fullQuote: Quote = {
success: true,
params,
sourceToken: {
@@ -690,17 +614,15 @@ class MayanRouteBase extends routes.AutomaticRoute<
async initiate(
request: routes.RouteTransferRequest,
signer: Signer,
- quote: Q,
+ quote: Quote,
to: ChainAddress,
) {
try {
- const referrerAddress = this.referrerAddress();
const originAddress = signer.address();
const destinationAddress = canonicalAddress(to);
const txs: TransactionId[] = [];
const rpc = await request.fromChain.getRpc();
const feeUnits = this.getFeeInBaseUnits(request, quote.params.amount);
- const isNewReferralEnabled = this.isNewReferralEnabled(request);
if (request.fromChain.chain === 'Solana') {
const { instructions, signers, lookupTables } =
@@ -717,7 +639,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
quote.details!,
originAddress,
destinationAddress,
- isNewReferralEnabled ? null : referrerAddress,
+ null,
rpc,
{ allowSwapperOffCurve: true },
));
@@ -801,7 +723,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
quote.details!,
originAddress,
destinationAddress,
- isNewReferralEnabled ? null : referrerAddress,
+ null,
undefined,
rpc,
options,
@@ -845,13 +767,14 @@ class MayanRouteBase extends routes.AutomaticRoute<
request.fromChain.chain,
);
+ const referrerAddress = this.referrerAddress();
const tokenAddress = this.toMayanAddress(request.source.id);
const isNativeToken = isNative(request.source.id.address);
const contractAddress = getEvmContractAddress(
request.fromChain.network,
feeUnits,
- isNewReferralEnabled,
+ referrerAddress.evm,
);
const amountUnits = amount.units(
@@ -905,7 +828,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
quote.details!,
originAddress,
destinationAddress,
- isNewReferralEnabled ? null : referrerAddress,
+ null,
originAddress,
Number(nativeChainId!),
undefined,
@@ -918,10 +841,9 @@ class MayanRouteBase extends routes.AutomaticRoute<
amountUnits,
feeUnits,
originAddress,
- referrerAddress?.evm || '',
tokenAddress,
isNativeToken,
- isNewReferralEnabled,
+ referrerAddress.evm,
);
txReqs.push(
@@ -970,7 +892,7 @@ class MayanRouteBase extends routes.AutomaticRoute<
}
}
- public override async *track(receipt: R, timeout?: number) {
+ public override async *track(receipt: Receipt, timeout?: number) {
if (isCompleted(receipt) || isRedeemed(receipt) || isRefunded(receipt))
return receipt;
@@ -1017,136 +939,13 @@ class MayanRouteBase extends routes.AutomaticRoute<
return `https://explorer.mayan.finance/swap/${txid}`;
}
- referrerAddress(): ReferrerAddresses | undefined {
+ referrerAddress() {
const { referrers } = this.constructor as ReferrerParams;
- if (!referrers || Object.keys(referrers).length < 1) {
- return undefined;
- }
-
return {
- solana: referrers.Solana || null,
- evm: referrers.Ethereum || null,
- sui: referrers.Sui || null,
+ solana: referrers?.Solana,
+ evm: referrers?.Ethereum,
+ sui: referrers?.Sui,
};
}
-
- getReferralParameters(request: routes.RouteTransferRequest): Pick<
- QuoteParams,
- 'referrerBps' | 'referrer'
- > & {
- isNewEvmReferralEnabled?: boolean;
- isNewSolanaReferralEnabled?: boolean;
- isNewSuiReferralEnabled?: boolean;
- } {
- const {
- referrers,
- getReferrerBps,
- isNewEvmReferralEnabled,
- isNewSolanaReferralEnabled,
- isNewSuiReferralEnabled,
- } = this.constructor as ReferrerParams;
-
- // TODO fix this function to when fully migrated to v2 referral
- const isReferralEnabled =
- !!referrers?.Solana && typeof getReferrerBps === 'function';
-
- return isReferralEnabled
- ? {
- referrer: referrers.Solana, // Mayan referrer system expects solana
- referrerBps: getReferrerBps(request),
- isNewEvmReferralEnabled,
- isNewSolanaReferralEnabled,
- isNewSuiReferralEnabled,
- }
- : {};
- }
-}
-
-export class MayanRoute
- extends MayanRouteBase
- implements routes.StaticRouteMethods
-{
- static meta = {
- name: 'MayanSwap',
- provider: 'Mayan',
- };
-
- override protocols: MayanProtocol[] = ['WH', 'MCTP', 'SWIFT', 'MONO_CHAIN'];
-}
-
-export class MayanRouteSWIFT
- extends MayanRouteBase
- implements routes.StaticRouteMethods
-{
- static meta = {
- name: 'MayanSwapSWIFT',
- provider: 'Mayan Swift',
- };
-
- override protocols: MayanProtocol[] = ['SWIFT'];
-}
-
-export class MayanRouteMCTP
- extends MayanRouteBase
- implements routes.StaticRouteMethods
-{
- static meta = {
- name: 'MayanSwapMCTP',
- provider: 'Mayan MCTP',
- };
-
- override protocols: MayanProtocol[] = ['MCTP'];
-}
-
-export class MayanRouteWH
- extends MayanRouteBase
- implements routes.StaticRouteMethods
-{
- static meta = {
- name: 'MayanSwapWH',
- provider: 'Mayan',
- };
-
- override protocols: MayanProtocol[] = ['WH'];
-}
-
-export class MayanRouteMONOCHAIN
- extends MayanRouteBase
- implements routes.StaticRouteMethods
-{
- static meta = {
- name: 'MayanSwapMONOCHAIN',
- provider: 'Mayan Mono Chain',
- };
-
- override protocols: MayanProtocol[] = ['MONO_CHAIN'];
-
- static supportsSameChainSwaps(network: Network, chain: Chain) {
- const platform = chainToPlatform(chain);
- const isPlatformSupported = platform === 'Solana' || platform === 'Evm';
- return network === 'Mainnet' && isPlatformSupported;
- }
-}
-
-export function createMayanRouteWithReferrerFee<
- N extends Network,
- T extends
- | typeof MayanRoute
- | typeof MayanRouteSWIFT
- | typeof MayanRouteMCTP
- | typeof MayanRouteWH
- | typeof MayanRouteMONOCHAIN,
->(
- classConstructor: T,
- properties: ReferrerParams = {},
-): T & ReferrerParams {
- if (
- properties?.referrers &&
- typeof properties?.getReferrerBps === 'function'
- ) {
- Object.assign(classConstructor, properties);
- }
-
- return classConstructor as T & ReferrerParams;
}
diff --git a/src/routes/mayan/MayanRouteFastMCTP.ts b/src/routes/mayan/MayanRouteFastMCTP.ts
new file mode 100644
index 000000000..5e3ceb2df
--- /dev/null
+++ b/src/routes/mayan/MayanRouteFastMCTP.ts
@@ -0,0 +1,16 @@
+import type { routes } from '@wormhole-foundation/sdk-connect';
+import type { Network } from '@wormhole-foundation/sdk-base';
+import { MayanProtocol } from './types';
+import { MayanRouteBase } from './MayanRouteBase';
+
+export class MayanRouteFastMCTP
+ extends MayanRouteBase
+ implements routes.StaticRouteMethods
+{
+ static meta = {
+ name: 'MayanSwapFastMCTP',
+ provider: 'Mayan MCTP',
+ };
+
+ override protocols: MayanProtocol[] = [MayanProtocol.FAST_MCTP];
+}
diff --git a/src/routes/mayan/MayanRouteMCTP.ts b/src/routes/mayan/MayanRouteMCTP.ts
new file mode 100644
index 000000000..2ffe4f095
--- /dev/null
+++ b/src/routes/mayan/MayanRouteMCTP.ts
@@ -0,0 +1,16 @@
+import type { Network } from '@wormhole-foundation/sdk-base';
+import type { routes } from '@wormhole-foundation/sdk-connect';
+import { MayanRouteBase } from './MayanRouteBase';
+import { MayanProtocol } from './types';
+
+export class MayanRouteMCTP
+ extends MayanRouteBase
+ implements routes.StaticRouteMethods
+{
+ static meta = {
+ name: 'MayanSwapMCTP',
+ provider: 'Mayan MCTP',
+ };
+
+ override protocols: MayanProtocol[] = [MayanProtocol.MCTP];
+}
diff --git a/src/routes/mayan/MayanRouteMONOCHAIN.ts b/src/routes/mayan/MayanRouteMONOCHAIN.ts
new file mode 100644
index 000000000..38aae33ad
--- /dev/null
+++ b/src/routes/mayan/MayanRouteMONOCHAIN.ts
@@ -0,0 +1,23 @@
+import { chainToPlatform } from '@wormhole-foundation/sdk-base';
+import type { Chain, Network } from '@wormhole-foundation/sdk-connect';
+import type { routes } from '@wormhole-foundation/sdk-connect';
+import { MayanRouteBase } from './MayanRouteBase';
+import { MayanProtocol } from './types';
+
+export class MayanRouteMONOCHAIN
+ extends MayanRouteBase
+ implements routes.StaticRouteMethods
+{
+ static meta = {
+ name: 'MayanSwapMONOCHAIN',
+ provider: 'Mayan Mono Chain',
+ };
+
+ override protocols: MayanProtocol[] = [MayanProtocol.MONO_CHAIN];
+
+ static supportsSameChainSwaps(network: Network, chain: Chain) {
+ const platform = chainToPlatform(chain);
+ const isPlatformSupported = platform === 'Solana' || platform === 'Evm';
+ return network === 'Mainnet' && isPlatformSupported;
+ }
+}
diff --git a/src/routes/mayan/MayanRouteSWIFT.ts b/src/routes/mayan/MayanRouteSWIFT.ts
new file mode 100644
index 000000000..ce63c23f0
--- /dev/null
+++ b/src/routes/mayan/MayanRouteSWIFT.ts
@@ -0,0 +1,16 @@
+import type { Network } from '@wormhole-foundation/sdk-base';
+import type { routes } from '@wormhole-foundation/sdk-connect';
+import { MayanRouteBase } from './MayanRouteBase';
+import { MayanProtocol } from './types';
+
+export class MayanRouteSWIFT
+ extends MayanRouteBase
+ implements routes.StaticRouteMethods
+{
+ static meta = {
+ name: 'MayanSwapSWIFT',
+ provider: 'Mayan Swift',
+ };
+
+ override protocols: MayanProtocol[] = [MayanProtocol.SWIFT];
+}
diff --git a/src/routes/mayan/MayanRouteWH.ts b/src/routes/mayan/MayanRouteWH.ts
new file mode 100644
index 000000000..71752408a
--- /dev/null
+++ b/src/routes/mayan/MayanRouteWH.ts
@@ -0,0 +1,16 @@
+import type { Network } from '@wormhole-foundation/sdk-base';
+import type { routes } from '@wormhole-foundation/sdk-connect';
+import { MayanRouteBase } from './MayanRouteBase';
+import { MayanProtocol } from './types';
+
+export class MayanRouteWH
+ extends MayanRouteBase
+ implements routes.StaticRouteMethods
+{
+ static meta = {
+ name: 'MayanSwapWH',
+ provider: 'Mayan WH',
+ };
+
+ override protocols: MayanProtocol[] = [MayanProtocol.WH];
+}
diff --git a/src/routes/mayan/evm/utils.ts b/src/routes/mayan/evm/utils.ts
index 8c14742c9..96026c29f 100644
--- a/src/routes/mayan/evm/utils.ts
+++ b/src/routes/mayan/evm/utils.ts
@@ -61,12 +61,12 @@ function createMayanForwarderShim() {
return { encodeFunctionData, getMsgValue };
}
-function useMayanForwarderShim(
+function isMayanForwarderShimEnabled(
network: Network,
feeUnits: bigint,
- isNewEvmReferralEnabled?: boolean,
+ referrer?: string,
) {
- if (feeUnits <= 0n || !isNewEvmReferralEnabled || network !== 'Mainnet') {
+ if (feeUnits <= 0n || !referrer || network !== 'Mainnet') {
return false;
}
@@ -76,11 +76,9 @@ function useMayanForwarderShim(
function getEvmContractAddress(
network: Network,
feeUnits: bigint,
- isNewEvmReferralEnabled?: boolean,
+ referrer?: string,
) {
- // TODO: Refactor, hooks shouldn't be called with in functions
- // eslint-disable-next-line react-hooks/rules-of-hooks
- if (useMayanForwarderShim(network, feeUnits, isNewEvmReferralEnabled)) {
+ if (isMayanForwarderShimEnabled(network, feeUnits, referrer)) {
return MayanForwarderShimContractAddress;
}
@@ -93,16 +91,13 @@ function createTransactionRequest(
amountUnits: bigint,
feeUnits: bigint,
sender: string,
- referrer: string,
tokenAddress: string,
isNativeToken: boolean,
- isNewEvmReferralEnabled?: boolean,
+ referrer?: string,
): TransactionRequest {
if (
!mayanTxRequest.data ||
- // TODO: Refactor, hooks shouldn't be called with in functions
- // eslint-disable-next-line react-hooks/rules-of-hooks
- !useMayanForwarderShim(network, feeUnits, isNewEvmReferralEnabled)
+ !isMayanForwarderShimEnabled(network, feeUnits, referrer)
) {
return mayanTxRequest;
}
@@ -111,7 +106,7 @@ function createTransactionRequest(
const data = mayanForwarder.encodeFunctionData(
mayanTxRequest.data,
- referrer,
+ referrer!,
feeUnits,
tokenAddress,
amountUnits,
diff --git a/src/routes/mayan/index.ts b/src/routes/mayan/index.ts
index 6c8d078b3..a9dfb85f4 100644
--- a/src/routes/mayan/index.ts
+++ b/src/routes/mayan/index.ts
@@ -1 +1,7 @@
-export * from './MayanRouteBase';
+export { MayanRoute } from './MayanRoute';
+export { MayanRouteSWIFT } from './MayanRouteSWIFT';
+export { MayanRouteMCTP } from './MayanRouteMCTP';
+export { MayanRouteWH } from './MayanRouteWH';
+export { MayanRouteMONOCHAIN } from './MayanRouteMONOCHAIN';
+export { MayanRouteFastMCTP } from './MayanRouteFastMCTP';
+export type { ReferrerParams } from './types';
diff --git a/src/routes/mayan/types.ts b/src/routes/mayan/types.ts
new file mode 100644
index 000000000..c65f7ac89
--- /dev/null
+++ b/src/routes/mayan/types.ts
@@ -0,0 +1,168 @@
+import type { Chain, Network } from '@wormhole-foundation/sdk-base';
+import type { routes } from '@wormhole-foundation/sdk-connect';
+import type { Quote as MayanQuote } from '@mayanfinance/swap-sdk';
+
+export enum MayanProtocol {
+ WH = 'WH',
+ MCTP = 'MCTP',
+ SWIFT = 'SWIFT',
+ FAST_MCTP = 'FAST_MCTP',
+ SHUTTLE = 'SHUTTLE',
+ MONO_CHAIN = 'MONO_CHAIN',
+}
+
+export type ReferrerParams = {
+ getReferrerBps?: (request: routes.RouteTransferRequest) => number;
+ referrers?: Partial>;
+};
+
+export type Options = {
+ gasDrop: number;
+ slippageBps: number | 'auto';
+ optimizeFor: 'cost' | 'speed';
+};
+
+export type NormalizedParams = {
+ slippageBps: number | 'auto';
+};
+
+export interface ValidatedParams
+ extends routes.ValidatedTransferParams {
+ normalizedParams: NormalizedParams;
+}
+
+export type Quote = routes.Quote;
+
+export type QuoteResult = routes.QuoteResult<
+ Options,
+ ValidatedParams,
+ MayanQuote
+>;
+
+export type Receipt = routes.Receipt;
+export type TransferParams = routes.TransferParams;
+export type ValidationResult = routes.ValidationResult;
+
+interface MayanTx {
+ txHash: string;
+ goals: MayanTransactionGoal[];
+ scannerUrl: string;
+}
+export interface TransactionStatus {
+ id: string;
+ trader: string;
+
+ sourceChain: string;
+ sourceTxHash: string;
+ sourceTxBlockNo: number;
+
+ transferSequence: string;
+ swapSequence: string;
+ redeemSequence: string;
+ refundSequence: string;
+ fulfillSequence: string;
+
+ deadline: string;
+
+ swapChain: string;
+ refundChain: string;
+
+ destChain: string;
+ destAddress: string;
+
+ fromTokenAddress: string;
+ fromTokenChain: string;
+ fromTokenSymbol: string;
+ fromAmount: string;
+ fromAmount64: any;
+
+ toTokenAddress: string;
+ toTokenChain: string;
+ toTokenSymbol: string;
+
+ stateAddr: string;
+ stateNonce: string;
+
+ toAmount: any;
+
+ transferSignedVaa: string;
+ swapSignedVaa: string;
+ redeemSignedVaa: string;
+ refundSignedVaa: string;
+ fulfillSignedVaa: string;
+
+ savedAt: string;
+ initiatedAt: string;
+ completedAt: string;
+ insufficientFees: boolean;
+ retries: number;
+
+ swapRelayerFee: string;
+ redeemRelayerFee: string;
+ refundRelayerFee: string;
+ bridgeFee: string;
+
+ statusUpdatedAt: string;
+
+ redeemTxHash: string;
+ refundTxHash: string;
+ fulfillTxHash: string;
+
+ unwrapRedeem: boolean;
+ unwrapRefund: boolean;
+
+ auctionAddress: string;
+ driverAddress: string;
+ mayanAddress: string;
+ referrerAddress: string;
+ auctionStateAddr: any;
+
+ auctionStateNonce: any;
+
+ gasDrop: string;
+ gasDrop64: any;
+
+ payloadId: number;
+ orderHash: string;
+
+ minAmountOut: any;
+ minAmountOut64: any;
+
+ service: string;
+
+ refundAmount: string;
+
+ posAddress: string;
+
+ unlockRecipient: any;
+
+ fromTokenLogoUri: string;
+ toTokenLogoUri: string;
+
+ fromTokenScannerUrl: string;
+ toTokenScannerUrl: string;
+
+ txs: MayanTx[];
+
+ clientStatus: MayanClientStatus;
+}
+
+export enum MayanClientStatus {
+ INPROGRESS = 'INPROGRESS',
+ COMPLETED = 'COMPLETED',
+ REFUNDED = 'REFUNDED',
+ CANCELED = 'CANCELED',
+}
+
+export enum MayanTransactionGoal {
+ // send from evm to solana
+ Send = 'SEND',
+ // bridge to destination chain
+ Bridge = 'BRIDGE',
+ // perform the swap
+ Swap = 'SWAP',
+ // register for auction
+ Register = 'REGISTER',
+ // settle on destination
+ Settle = 'SETTLE',
+}
diff --git a/src/routes/mayan/utils.ts b/src/routes/mayan/utils.ts
index 2b1e03b3f..900ece178 100644
--- a/src/routes/mayan/utils.ts
+++ b/src/routes/mayan/utils.ts
@@ -1,11 +1,7 @@
-import type {
- ChainName as MayanChainName,
- SolanaTransactionSigner,
-} from '@mayanfinance/swap-sdk';
+import type { ChainName as MayanChainName } from '@mayanfinance/swap-sdk';
import type { ChainName as MayanTestnetChainName } from '@testnet-mayan/swap-sdk';
// Testnet chain names supported by @testnet-mayan/swap-sdk
-import { Transaction, VersionedTransaction } from '@solana/web3.js';
import type {
AttestationReceipt,
Chain,
@@ -13,8 +9,6 @@ import type {
RedeemedTransferReceipt,
RefundedTransferReceipt,
SourceInitiatedTransferReceipt,
- Signer,
- TokenId,
TransactionId,
routes,
Network,
@@ -23,15 +17,11 @@ import {
TransferState,
deserialize,
encoding,
- isSignOnlySigner,
toChain,
- circle,
- Wormhole,
} from '@wormhole-foundation/sdk-connect';
-import { isEvmNativeSigner } from '@wormhole-foundation/sdk-evm';
-import type { SolanaUnsignedTransaction } from '@wormhole-foundation/sdk-solana';
import axios from 'axios';
-import type { ethers } from 'ethers';
+import type { TransactionStatus } from './types';
+import { MayanClientStatus, MayanTransactionGoal } from './types';
export function getNativeContractAddress(chain: Chain): string {
if (chain === 'Sui') return '0x2::sui::SUI';
@@ -75,6 +65,7 @@ const chainNameMap = {
Unichain: 'unichain',
Sui: 'sui',
HyperEVM: 'hyperevm',
+ Linea: 'linea',
} as Record;
// Mapping of Wormhole chains to testnet Mayan chain names
@@ -128,56 +119,6 @@ export function supportedChains(network?: Network): Chain[] {
return Object.keys(chainNameMap) as Chain[];
}
-// https://solana-labs.github.io/solana-web3.js/classes/Transaction.html
-function isTransaction(tx: any): tx is Transaction {
- return typeof (tx).verifySignatures === 'function';
-}
-
-export function mayanSolanaSigner(signer: Signer): SolanaTransactionSigner {
- if (!isSignOnlySigner(signer))
- throw new Error('Signer must be a SignOnlySigner');
-
- return async (
- tx: T,
- ): Promise => {
- const ust: SolanaUnsignedTransaction<'Mainnet'> = {
- transaction: { transaction: tx },
- description: 'Mayan.InitiateSwap',
- network: 'Mainnet',
- chain: 'Solana',
- parallelizable: false,
- };
- const signed = (await signer.sign([ust])) as Buffer[];
- if (isTransaction(tx)) return Transaction.from(signed[0]!) as T;
- else return VersionedTransaction.deserialize(signed[0]!) as T;
- };
-}
-
-export function mayanEvmSigner(signer: Signer): ethers.Signer {
- if (isEvmNativeSigner(signer))
- return signer.unwrap() as unknown as ethers.Signer;
-
- throw new Error('Signer must be an EvmNativeSigner');
-}
-
-export function mayanEvmProvider(signer: ethers.Signer) {
- return {
- getBlock: async function (): Promise<{ timestamp: number }> {
- const block = await signer.provider!.getBlock('latest');
- if (block === null)
- throw new Error('Failed to get latest Ethereum block');
- return block;
- },
- };
-}
-
-export enum MayanClientStatus {
- INPROGRESS = 'INPROGRESS',
- COMPLETED = 'COMPLETED',
- REFUNDED = 'REFUNDED',
- CANCELED = 'CANCELED',
-}
-
const possibleVaaTypes = [
// Bridge to swap chain (solana)
'transfer',
@@ -189,124 +130,6 @@ const possibleVaaTypes = [
'refund',
];
-export enum MayanTransactionGoal {
- // send from evm to solana
- Send = 'SEND',
- // bridge to destination chain
- Bridge = 'BRIDGE',
- // perform the swap
- Swap = 'SWAP',
- // register for auction
- Register = 'REGISTER',
- // settle on destination
- Settle = 'SETTLE',
-}
-
-export interface TransactionStatus {
- id: string;
- trader: string;
-
- sourceChain: string;
- sourceTxHash: string;
- sourceTxBlockNo: number;
-
- transferSequence: string;
- swapSequence: string;
- redeemSequence: string;
- refundSequence: string;
- fulfillSequence: string;
-
- deadline: string;
-
- swapChain: string;
- refundChain: string;
-
- destChain: string;
- destAddress: string;
-
- fromTokenAddress: string;
- fromTokenChain: string;
- fromTokenSymbol: string;
- fromAmount: string;
- fromAmount64: any;
-
- toTokenAddress: string;
- toTokenChain: string;
- toTokenSymbol: string;
-
- stateAddr: string;
- stateNonce: string;
-
- toAmount: any;
-
- transferSignedVaa: string;
- swapSignedVaa: string;
- redeemSignedVaa: string;
- refundSignedVaa: string;
- fulfillSignedVaa: string;
-
- savedAt: string;
- initiatedAt: string;
- completedAt: string;
- insufficientFees: boolean;
- retries: number;
-
- swapRelayerFee: string;
- redeemRelayerFee: string;
- refundRelayerFee: string;
- bridgeFee: string;
-
- statusUpdatedAt: string;
-
- redeemTxHash: string;
- refundTxHash: string;
- fulfillTxHash: string;
-
- unwrapRedeem: boolean;
- unwrapRefund: boolean;
-
- auctionAddress: string;
- driverAddress: string;
- mayanAddress: string;
- referrerAddress: string;
- auctionStateAddr: any;
-
- auctionStateNonce: any;
-
- gasDrop: string;
- gasDrop64: any;
-
- payloadId: number;
- orderHash: string;
-
- minAmountOut: any;
- minAmountOut64: any;
-
- service: string;
-
- refundAmount: string;
-
- posAddress: string;
-
- unlockRecipient: any;
-
- fromTokenLogoUri: string;
- toTokenLogoUri: string;
-
- fromTokenScannerUrl: string;
- toTokenScannerUrl: string;
-
- txs: Tx[];
-
- clientStatus: MayanClientStatus;
-}
-
-export interface Tx {
- txHash: string;
- goals: MayanTransactionGoal[];
- scannerUrl: string;
-}
-
export function txStatusToReceipt(txStatus: TransactionStatus): routes.Receipt {
const srcChain = toWormholeChainName(txStatus.sourceChain);
const dstChain = toWormholeChainName(txStatus.destChain);
@@ -449,15 +272,3 @@ export async function getTransactionStatus(
}
return null;
}
-
-export function getUSDCTokenId(
- chain: Chain,
- network: Network,
-): TokenId | undefined {
- const usdcContract = circle.usdcContract.get(network, chain);
- if (!usdcContract) {
- return undefined;
- }
-
- return Wormhole.tokenId(chain, usdcContract);
-}