From ba3f51d6ed812870b0bd3649ad3094a7994a087c Mon Sep 17 00:00:00 2001 From: Daniel <80175477+dan437@users.noreply.github.com> Date: Fri, 25 Jun 2021 15:10:24 +0200 Subject: [PATCH] Add support for fiat on-ramp via Transak (#11376) --- app/_locales/en/messages.json | 9 ++ app/images/transak.svg | 112 ++++++++++++++++++ app/scripts/constants/on-ramp.js | 1 + app/scripts/lib/buy-eth-url.js | 19 +++ app/scripts/lib/buy-eth-url.test.js | 12 +- .../deposit-ether-modal.component.js | 27 +++++ .../deposit-ether-modal.container.js | 3 + 7 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 app/images/transak.svg create mode 100644 app/scripts/constants/on-ramp.js diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 54ede46cd..521cebef2 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -268,6 +268,12 @@ "buy": { "message": "Buy" }, + "buyWithTransak": { + "message": "Buy ETH with Transak" + }, + "buyWithTransakDescription": { + "message": "Transak supports debit card and bank transfers (depending on location) in 59+ countries. ETH deposits into your MetaMask account." + }, "buyWithWyre": { "message": "Buy ETH with Wyre" }, @@ -420,6 +426,9 @@ "continue": { "message": "Continue" }, + "continueToTransak": { + "message": "Continue to Transak" + }, "continueToWyre": { "message": "Continue to Wyre" }, diff --git a/app/images/transak.svg b/app/images/transak.svg new file mode 100644 index 000000000..8f8d7790a --- /dev/null +++ b/app/images/transak.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/scripts/constants/on-ramp.js b/app/scripts/constants/on-ramp.js new file mode 100644 index 000000000..335d7a9ad --- /dev/null +++ b/app/scripts/constants/on-ramp.js @@ -0,0 +1 @@ +export const TRANSAK_API_KEY = '25ac1309-a49b-4411-b20e-5e56c61a5b1c'; // It's a public key, which will be included in a URL for Transak. diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 2cb1b0e81..f36bdb468 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -5,6 +5,23 @@ import { RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, } from '../../../shared/constants/network'; +import { TRANSAK_API_KEY } from '../constants/on-ramp'; + +/** + * Create a Transak Checkout URL. + * API docs here: https://www.notion.so/Query-Parameters-9ec523df3b874ec58cef4fa3a906f238 + * @param {String} address Ethereum destination address + * @returns String + */ +const createTransakUrl = (address) => { + const queryParams = new URLSearchParams({ + apiKey: TRANSAK_API_KEY, + hostURL: 'https://metamask.io', + defaultCryptoCurrency: 'ETH', + walletAddress: address, + }); + return `https://global.transak.com/?${queryParams}`; +}; /** * Gives the caller a url at which the user can acquire eth, depending on the network they are in @@ -26,6 +43,8 @@ export default function getBuyEthUrl({ chainId, address, service }) { switch (service) { case 'wyre': return `https://pay.sendwyre.com/purchase?dest=ethereum:${address}&destCurrency=ETH&accountId=AC-7AG3W4XH4N2&paymentMethod=debit-card`; + case 'transak': + return createTransakUrl(address); case 'metamask-faucet': return 'https://faucet.metamask.io/'; case 'rinkeby-faucet': diff --git a/app/scripts/lib/buy-eth-url.test.js b/app/scripts/lib/buy-eth-url.test.js index 01837c8ef..c8d7dca0c 100644 --- a/app/scripts/lib/buy-eth-url.test.js +++ b/app/scripts/lib/buy-eth-url.test.js @@ -5,6 +5,7 @@ import { RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, } from '../../../shared/constants/network'; +import { TRANSAK_API_KEY } from '../constants/on-ramp'; import getBuyEthUrl from './buy-eth-url'; describe('buy-eth-url', function () { @@ -23,7 +24,7 @@ describe('buy-eth-url', function () { chainId: KOVAN_CHAIN_ID, }; - it('returns wyre url with address for network 1', function () { + it('returns Wyre url with an ETH address for Ethereum mainnet', function () { const wyreUrl = getBuyEthUrl(mainnet); assert.equal( @@ -32,6 +33,15 @@ describe('buy-eth-url', function () { ); }); + it('returns Transak url with an ETH address for Ethereum mainnet', function () { + const transakUrl = getBuyEthUrl({ ...mainnet, service: 'transak' }); + + assert.equal( + transakUrl, + `https://global.transak.com/?apiKey=${TRANSAK_API_KEY}&hostURL=https%3A%2F%2Fmetamask.io&defaultCryptoCurrency=ETH&walletAddress=0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc`, + ); + }); + it('returns metamask ropsten faucet for network 3', function () { const ropstenUrl = getBuyEthUrl(ropsten); assert.equal(ropstenUrl, 'https://faucet.metamask.io/'); diff --git a/ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js b/ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js index 3f1775a47..59fb89831 100644 --- a/ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js +++ b/ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js @@ -14,6 +14,7 @@ export default class DepositEtherModal extends Component { isTestnet: PropTypes.bool.isRequired, isMainnet: PropTypes.bool.isRequired, toWyre: PropTypes.func.isRequired, + toTransak: PropTypes.func.isRequired, address: PropTypes.string.isRequired, toFaucet: PropTypes.func.isRequired, hideWarning: PropTypes.func.isRequired, @@ -87,6 +88,7 @@ export default class DepositEtherModal extends Component { const { chainId, toWyre, + toTransak, address, toFaucet, isTestnet, @@ -138,6 +140,31 @@ export default class DepositEtherModal extends Component { }, hide: !isMainnet, })} + {this.renderRow({ + logo: ( +
+ ), + title: this.context.t('buyWithTransak'), + text: this.context.t('buyWithTransakDescription'), + buttonLabel: this.context.t('continueToTransak'), + onButtonClick: () => { + this.context.metricsEvent({ + eventOpts: { + category: 'Accounts', + action: 'Deposit Ether', + name: 'Click buy Ether via Transak', + }, + }); + toTransak(address); + }, + hide: !isMainnet, + })} {this.renderRow({ logo: ( { dispatch(buyEth({ service: 'wyre', address })); }, + toTransak: (address) => { + dispatch(buyEth({ service: 'transak', address })); + }, hideModal: () => { dispatch(hideModal()); },