Skip to content

Commit

Permalink
created a special page for multibuy
Browse files Browse the repository at this point in the history
  • Loading branch information
IAmMorrow committed Mar 22, 2022
1 parent 2c0534a commit c8022fa
Show file tree
Hide file tree
Showing 2 changed files with 346 additions and 0 deletions.
48 changes: 48 additions & 0 deletions pages/buy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react";
import { useRouter } from "next/router";
import CoinifyWidgetBuy from "../src/Coinify/CoinifyWidgetBuy";

type QueryParams = {
accountId?: string;
accountAddress?: string;
language?: string;
fiatCurrencyId?: string;
cryptoCurrencyId?: string;
primaryColor?: string;
mode?: "onRamp" | "offRamp";
fiatAmount?: string;
cryptoAmount?: string;
};

const Page = () => {
const router = useRouter();

const {
accountAddress,
language,
fiatCurrencyId,
cryptoCurrencyId,
primaryColor,
fiatAmount,
cryptoAmount,
} = router.query as QueryParams;

if (accountAddress && cryptoCurrencyId) {
return (
<CoinifyWidgetBuy
accountAddress={accountAddress}
currency={cryptoCurrencyId}
fiatCurrencyId={fiatCurrencyId}
mode={"onRamp"}
fiatAmount={fiatAmount}
cryptoAmount={cryptoAmount}
language={language}
primaryColor={primaryColor}
/>
);
}

return null;
};

export default Page;
298 changes: 298 additions & 0 deletions src/Coinify/CoinifyWidgetBuy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
// @flow

import React, { useState, useEffect, useRef, useCallback } from "react";
import styled from "styled-components";
import querystring from "querystring";
import { useApi } from "../providers/LedgerLiveSDKProvider";

type CoinifyConfig = {
host: string;
url: string;
partnerId: string;
};

const COINIFY_CONFIG: { [key: string]: CoinifyConfig } = {
sandbox: {
host: "https://trade-ui.sandbox.coinify.com",
url: "https://trade-ui.sandbox.coinify.com/widget",
partnerId: "191f0c7f-076d-459f-bf2d-833465bfadc2",
},
prod: {
host: "https://trade-ui.coinify.com",
url: "https://trade-ui.coinify.com/widget",
partnerId: "191f0c7f-076d-459f-bf2d-833465bfadc2",
},
};

const CustomIframe = styled.iframe`
border: none;
width: 100%;
height: 100%;
flex: 1;
transition: opacity 200ms ease-out;
`;

type CoinifyWidgetConfig = {
primaryColor?: string;
partnerId: string;
cryptoCurrencies?: string | null;
defaultFiatCurrency?: string;
address?: string | null;
targetPage: string;
addressConfirmation?: boolean;
transferConfirmation?: boolean;
transferOutMedia?: string;
transferInMedia?: string;
confirmMessages?: boolean;
buyAmount?: string;
sellAmount?: string;
};

type Props = {
accountAddress: string;
currency: string;
fiatCurrencyId?: string;
mode: "onRamp" | "offRamp" | "history";
cryptoAmount?: string;
fiatAmount?: string;
language?: string;
primaryColor?: string;
};

const CoinifyWidgetBuy = ({
accountAddress,
currency,
fiatCurrencyId,
mode,
fiatAmount,
cryptoAmount,
primaryColor,
}: Props) => {
const api = useApi();

const env = new URLSearchParams(window.location.search).get("env") || "prod";

const tradeId = useRef(null);
const [widgetLoaded, setWidgetLoaded] = useState(false);

const widgetRef: { current: null | HTMLIFrameElement } = useRef(null);

const coinifyConfig = COINIFY_CONFIG[env];
const widgetConfig: CoinifyWidgetConfig = {
primaryColor,
partnerId: coinifyConfig.partnerId,
cryptoCurrencies: currency ? currency : null,
defaultFiatCurrency: fiatCurrencyId ? fiatCurrencyId : undefined,
address: accountAddress,
targetPage: mode,
};

// FIXME: could use switch case?
if (mode === "onRamp") {
widgetConfig.transferOutMedia = "blockchain";
widgetConfig.confirmMessages = true;
widgetConfig.buyAmount = fiatAmount;
widgetConfig.sellAmount = cryptoAmount;
}

if (mode === "offRamp") {
widgetConfig.transferInMedia = "blockchain";
widgetConfig.confirmMessages = true;
widgetConfig.buyAmount = fiatAmount;
widgetConfig.sellAmount = cryptoAmount;
}

if (mode === "history") {
widgetConfig.transferOutMedia = "";
widgetConfig.transferInMedia = "";
}

useEffect(() => {
if (!currency) return;
if (mode === "onRamp" && accountAddress) {
console.log(`Coinify Start OnRamp Widget | currencyName: ${currency}`);
}
if (mode === "offRamp" && accountAddress) {
console.log(`Coinify Start OffRamp Widget | currencyName: ${currency}`);
}
if (mode === "history") {
console.log("Coinify Start History Widget");
}
}, [accountAddress, currency, mode]);

const url = `${coinifyConfig.url}?${querystring.stringify(widgetConfig)}`;

const handleOnResultBuy = useCallback(
(address: string) => {
if (
!widgetRef?.current?.contentWindow ||
!accountAddress ||
mode !== "onRamp"
) {
return;
}

widgetRef.current.contentWindow.postMessage(
{
type: "event",
event: "trade.confirm-trade-prepared",
context: {
address,
confirmed: true,
},
},
coinifyConfig.host
);
if (currency) {
console.log(`Coinify Confirm OnRamp End | currencyName: ${currency}`);
}
},
[coinifyConfig.host, currency, accountAddress, mode]
);

const handleOnResult = useCallback(() => {
if (widgetRef?.current?.contentWindow) {
if (accountAddress && mode === "onRamp") {
widgetRef.current.contentWindow.postMessage(
{
type: "event",
event: "trade.confirm-trade-prepared",
context: {
address: accountAddress,
confirmed: true,
},
},
coinifyConfig.host
);
if (currency) {
console.log(`Coinify Confirm Buy End | currencyName: ${currency}`);
}
}
if (tradeId.current && mode === "offRamp") {
widgetRef.current.contentWindow.postMessage(
{
type: "event",
event: "trade.confirm-trade-created",
context: {
confirmed: true,
transferInitiated: true,
tradeId: tradeId.current,
},
},
coinifyConfig.host
);
if (currency) {
console.log(`Coinify Confirm Sell End | currencyName: ${currency}`);
}
}
}
}, [coinifyConfig.host, currency, accountAddress, mode]);

const handleOnCancel = useCallback(() => {
if (widgetRef?.current?.contentWindow) {
if (mode === "onRamp" && accountAddress) {
widgetRef.current.contentWindow.postMessage(
{
type: "event",
event: "trade.confirm-trade-prepared",
context: {
address: accountAddress,
confirmed: false,
},
},
coinifyConfig.host
);
}
if (mode === "offRamp") {
widgetRef.current.contentWindow.postMessage(
{
type: "event",
event: "trade.confirm-trade-created",
context: {
confirmed: false,
},
},
coinifyConfig.host
);
}
}
}, [coinifyConfig.host, accountAddress, mode]);

useEffect(() => {
if (!accountAddress) return;

function onMessage(e: any) {
if (!e.isTrusted || e.origin !== coinifyConfig.host || !e.data) return;
const { type, event, context } = e.data;

if (type !== "event") return;
switch (event) {
case "trade.trade-created":
tradeId.current = context.id;
if (mode === "onRamp" && widgetRef.current?.contentWindow) {
widgetRef.current.contentWindow.postMessage(
{
type: "event",
event: "trade.confirm-trade-created",
context: {
confirmed: true,
tradeId: tradeId.current,
},
},
coinifyConfig.host
);
}
break;
case "trade.trade-prepared":
break;
case "trade.receive-account-changed":
if (accountAddress && context.address === accountAddress) {
// FIXME: VERIFY ADDRESS

// FIXME: handle cancel / error
handleOnResultBuy(accountAddress);

if (currency) {
console.log(
`Coinify Confirm Buy Start | currencyName: ${currency}`
);
}
} else {
// Address mismatch, potential attack
}
break;
case "trade.trade-placed":
if (currency) {
console.log(
`Coinify Widget Event Trade Placed | currencyName: ${currency}`
);
}
break;
}
}

window.addEventListener("message", onMessage, false);
return () => window.removeEventListener("message", onMessage, false);
}, [
accountAddress,
coinifyConfig,
currency,
handleOnCancel,
handleOnResult,
handleOnResultBuy,
mode,
api,
]);

return (
<CustomIframe
src={url}
ref={widgetRef}
style={{ opacity: widgetLoaded ? 1 : 0 }}
onLoad={() => setTimeout(() => setWidgetLoaded(true), 500)}
allow="camera"
/>
);
};

export default CoinifyWidgetBuy;

1 comment on commit c8022fa

@vercel
Copy link

@vercel vercel bot commented on c8022fa Mar 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.