Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 75 additions & 55 deletions packages/checkout/sdk/src/fiatRamp/fiatRamp.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
import { Environment } from '@imtbl/config';
import { AxiosResponse } from 'axios';
import { CheckoutConfiguration } from '../config';
import { RemoteConfigFetcher } from '../config/remoteConfigFetcher';
import { FiatRampService, FiatRampWidgetParams } from './fiatRamp';
import { ExchangeType, OnRampProvider } from '../types';
import { HttpClient } from '../api/http';

const defaultURL = 'https://global-stg.transak.com';
const defaultParams = {
apiKey: 'mock-api-key',
network: 'immutablezkevm',
defaultPaymentMethod: 'credit_debit_card',
disablePaymentMethods: '',
productsAvailed: 'buy',
exchangeScreenTitle: 'Buy',
themeColor: '0D0D0D',
};

const defaultWidgetUrl = `${defaultURL}?${new URLSearchParams(
defaultParams,
).toString()}`;
const SANDBOX_WIDGET_URL = 'https://api.sandbox.immutable.com/checkout/v1/widget-url';

jest.mock('../config/remoteConfigFetcher');

Expand All @@ -29,6 +18,9 @@ describe('FiatRampService', () => {

beforeEach(() => {
mockedHttpClient = new HttpClient() as jest.Mocked<HttpClient>;
mockedHttpClient.post = jest.fn().mockResolvedValue({
data: { url: defaultURL },
} as AxiosResponse);
});

describe('feeEstimate', () => {
Expand Down Expand Up @@ -111,86 +103,114 @@ describe('FiatRampService', () => {
);
fiatRampService = new FiatRampService(config);
});

it(`should return widget url with non-configurable query params when onRampProvider is Transak' +
'and default to IMX`, async () => {
const params: FiatRampWidgetParams = {
const params = {
exchangeType: ExchangeType.ONRAMP,
isPassport: false,
};
const result = await fiatRampService.createWidgetUrl(params);
expect(result).toContain(defaultWidgetUrl);
expect(result).toContain('&defaultCryptoCurrency=IMX');
expect(result).not.toContain('&email=');
expect(result).not.toContain(
'&isAutoFillUserData=true&disableWalletAddressForm=true',
} as FiatRampWidgetParams;
const result = await fiatRampService.createWidgetUrl(params, mockedHttpClient);
expect(result).toContain('https://global-stg.transak.com');
expect(mockedHttpClient.post).toHaveBeenCalledWith(
SANDBOX_WIDGET_URL,
expect.objectContaining({
default_crypto_currency: 'IMX',
}),
{ method: 'POST' },
);
expect(result).not.toContain('&defaultCryptoAmount=');
expect(result).not.toContain('&walletAddress=');
});

it(`should return widget url with encoded email, isAutoFillUserData and disableWalletAddressForm query params
for passport users`, async () => {
const params: FiatRampWidgetParams = {
const params = {
exchangeType: ExchangeType.ONRAMP,
isPassport: true,
email: '[email protected]',
};
const result = await fiatRampService.createWidgetUrl(params);
expect(result).toContain(defaultWidgetUrl);
expect(result).toContain('&email=passport.user%2540immutable.com');
expect(result).toContain('&isAutoFillUserData=true');
expect(result).toContain('&disableWalletAddressForm=true');
} as FiatRampWidgetParams;
const result = await fiatRampService.createWidgetUrl(params, mockedHttpClient);
expect(result).toContain('https://global-stg.transak.com');
expect(mockedHttpClient.post).toHaveBeenCalledWith(
SANDBOX_WIDGET_URL,
expect.objectContaining({
email: '[email protected]',
is_auto_fill_user_data: true,
disable_wallet_address_form: true,
}),
{ method: 'POST' },
);
});

it(`should return widget url with defaultFiatAmount and defaultCryptoCurrency query params when tokenAmount and
tokenSymbol are not present`, async () => {
const params: FiatRampWidgetParams = {
const params = {
exchangeType: ExchangeType.ONRAMP,
isPassport: false,
};
const result = await fiatRampService.createWidgetUrl(params);
expect(result).toContain(defaultWidgetUrl);
expect(result).toContain('&defaultFiatAmount=50');
expect(result).toContain('&defaultCryptoCurrency=IMX');
expect(result).not.toContain('&defaultCryptoAmount=100');
expect(result).not.toContain('&cryptoCurrencyCode=ETH');
} as FiatRampWidgetParams;
const result = await fiatRampService.createWidgetUrl(params, mockedHttpClient);
expect(result).toContain('https://global-stg.transak.com');
expect(mockedHttpClient.post).toHaveBeenCalledWith(
SANDBOX_WIDGET_URL,
expect.objectContaining({
default_fiat_amount: 50,
default_crypto_currency: 'IMX',
}),
{ method: 'POST' },
);
});

it(`should return widget url with defaultCryptoAmount and cryptoCurrencyCode query params when tokenAmount and
tokenSymbol is present`, async () => {
const params: FiatRampWidgetParams = {
const params = {
exchangeType: ExchangeType.ONRAMP,
isPassport: false,
tokenAmount: '100',
tokenSymbol: 'ETH',
};
const result = await fiatRampService.createWidgetUrl(params);
expect(result).toContain(defaultWidgetUrl);
expect(result).toContain('&defaultCryptoAmount=100');
expect(result).toContain('&cryptoCurrencyCode=ETH');
expect(result).not.toContain('&defaultCryptoCurrency=IMX');
} as FiatRampWidgetParams;
const result = await fiatRampService.createWidgetUrl(params, mockedHttpClient);
expect(result).toContain('https://global-stg.transak.com');
expect(mockedHttpClient.post).toHaveBeenCalledWith(
SANDBOX_WIDGET_URL,
expect.objectContaining({
default_crypto_amount: '100',
crypto_currency_code: 'ETH',
}),
{ method: 'POST' },
);
});

it('should return widget url with walletAddress query params when walletAddress is present', async () => {
const params: FiatRampWidgetParams = {
const params = {
exchangeType: ExchangeType.ONRAMP,
isPassport: false,
walletAddress: '0x1234567890',
};
const result = await fiatRampService.createWidgetUrl(params);
expect(result).toContain(defaultWidgetUrl);
expect(result).toContain('&walletAddress=0x1234567890');
} as FiatRampWidgetParams;
const result = await fiatRampService.createWidgetUrl(params, mockedHttpClient);
expect(result).toContain('https://global-stg.transak.com');
expect(mockedHttpClient.post).toHaveBeenCalledWith(
SANDBOX_WIDGET_URL,
expect.objectContaining({
wallet_address: '0x1234567890',
}),
{ method: 'POST' },
);
});

it('should return widget url with allowed crypto tokens in query params when allowed list is present', async () => {
const params: FiatRampWidgetParams = {
const params = {
exchangeType: ExchangeType.ONRAMP,
isPassport: false,
allowedTokens: ['ETH', 'IMX'],
};
const result = await fiatRampService.createWidgetUrl(params);
expect(result).toContain(defaultWidgetUrl);
expect(result).toContain('&cryptoCurrencyList=eth%2Cimx');
} as FiatRampWidgetParams;
const result = await fiatRampService.createWidgetUrl(params, mockedHttpClient);
expect(result).toContain('https://global-stg.transak.com');
expect(mockedHttpClient.post).toHaveBeenCalledWith(
SANDBOX_WIDGET_URL,
expect.objectContaining({
crypto_currency_list: 'eth,imx',
}),
{ method: 'POST' },
);
});
});
});
63 changes: 37 additions & 26 deletions packages/checkout/sdk/src/fiatRamp/fiatRamp.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { ExchangeType } from '../types/fiatRamp';
import { OnRampConfig, OnRampProvider, OnRampProviderFees } from '../types';
import { CheckoutConfiguration } from '../config';
import { TRANSAK_API_BASE_URL } from '../env';
import { IMMUTABLE_API_BASE_URL } from '../env';
import { HttpClient } from '../api/http';

export interface FiatRampWidgetParams {
exchangeType: ExchangeType;
isPassport: boolean;
walletAddress?: string;
tokenAmount?: string;
tokenSymbol?: string;
email?: string;
allowedTokens?: string[];
walletAddress: string | undefined;
tokenAmount: string | undefined;
tokenSymbol: string | undefined;
email: string | undefined;
allowedTokens: string[] | undefined;
showMenu: boolean | undefined;
customSubTitle: string | undefined;
}

export class FiatRampService {
Expand All @@ -31,35 +34,42 @@ export class FiatRampService {
return config[OnRampProvider.TRANSAK]?.fees;
}

public async createWidgetUrl(params: FiatRampWidgetParams): Promise<string> {
return await this.getTransakWidgetUrl(params);
public async createWidgetUrl(
params: FiatRampWidgetParams,
httpClient = new HttpClient(),
): Promise<string> {
return await this.getTransakWidgetUrl(params, httpClient);
}

private async getTransakWidgetUrl(
params: FiatRampWidgetParams,
httpClient: HttpClient,
): Promise<string> {
const onRampConfig = (await this.config.remote.getConfig(
'onramp',
)) as OnRampConfig;

const widgetUrl = TRANSAK_API_BASE_URL[this.config.environment];
const createWidgetUrl = `${IMMUTABLE_API_BASE_URL[this.config.environment]}/checkout/v1/widget-url`;

let widgetParams: Record<string, any> = {
apiKey: onRampConfig[OnRampProvider.TRANSAK].publishableApiKey,
api_key: onRampConfig[OnRampProvider.TRANSAK].publishableApiKey,
network: 'immutablezkevm',
defaultPaymentMethod: 'credit_debit_card',
disablePaymentMethods: '',
productsAvailed: 'buy',
exchangeScreenTitle: 'Buy',
themeColor: '0D0D0D',
defaultCryptoCurrency: params.tokenSymbol || 'IMX',
default_payment_method: 'credit_debit_card',
disable_payment_methods: '',
products_availed: 'buy',
exchange_screen_title: params.customSubTitle === '' ? ' ' : (params.customSubTitle ?? 'Buy'),
theme_color: 'FFFFFF', // this only controls the background colour of the Buy button
default_crypto_currency: params.tokenSymbol || 'IMX',
hide_menu: !(params.showMenu ?? true),
referrer_domain: window.location.origin,
};

if (params.isPassport && params.email) {
widgetParams = {
...widgetParams,
email: encodeURIComponent(params.email),
isAutoFillUserData: true,
disableWalletAddressForm: true,
email: params.email,
is_auto_fill_user_data: true,
disable_wallet_address_form: true,
};
}

Expand All @@ -69,31 +79,32 @@ export class FiatRampService {
if (params.tokenAmount && params.tokenSymbol) {
widgetParams = {
...widgetParams,
defaultCryptoAmount: params.tokenAmount,
cryptoCurrencyCode: params.tokenSymbol,
default_crypto_amount: params.tokenAmount,
crypto_currency_code: params.tokenSymbol,
};
} else {
widgetParams = {
...widgetParams,
defaultFiatAmount: 50,
defaultFiatCurrency: 'usd',
default_fiat_amount: 50,
default_fiat_currency: 'usd',
};
}

if (params.walletAddress) {
widgetParams = {
...widgetParams,
walletAddress: params.walletAddress,
wallet_address: params.walletAddress,
};
}

if (params.allowedTokens) {
widgetParams = {
...widgetParams,
cryptoCurrencyList: params.allowedTokens?.join(',').toLowerCase(),
crypto_currency_list: params.allowedTokens?.join(',').toLowerCase(),
};
}

return `${widgetUrl}?${new URLSearchParams(widgetParams).toString()}`;
const response = await httpClient.post(createWidgetUrl, widgetParams, { method: 'POST' });
return response.data.url;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export function TransakIframe(props: TransakIframeProps) {
}}
onLoad={onLoad}
onError={() => onFailedToLoad?.()}
referrerPolicy="strict-origin-when-cross-origin"
/>
);
}
Loading