-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
346 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
c8022fa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs: