@atomicfi/transact-javascript
Version:
Atomic Transact Javascript SDK.
180 lines (159 loc) • 4.95 kB
JavaScript
let atomicIframeEventListener
let atomicProduct = {
DEPOSIT: 'deposit',
VERIFY: 'verify',
IDENTIFY: 'identify',
WITHHOLD: 'withhold'
}
let atomicSDK = {
/**
* Launch the Transact experience
* @param options - Options for launching Transact
* @param options.config - Atomic config object to customize Transact - https://docs.atomicfi.com/reference/transact-sdk#sdk-parameters
* @param options.onInteraction - Callback for when a user interacts with Transact
* @param options.onDataRequest - Callback for when Transact requests additional data
* @param options.onFinish - Callback for when Transact is finished
* @param options.onClose - Callback for when Transact is closed
* @param options.onOpenUrl - Callback for when Transact opens an external URL
*/
transact: ({
config,
container = undefined,
environmentOverride = undefined,
onInteraction = undefined,
onDataRequest = undefined,
onFinish = undefined,
onClose = undefined,
onOpenUrl = undefined
} = {}) => {
config = config || {}
onInteraction = onInteraction || function () {}
onDataRequest = onDataRequest || function () {}
onFinish = onFinish || function () {}
onClose = onClose || function () {}
onOpenUrl = onOpenUrl || undefined
const origin = environmentOverride || 'https://transact.atomicfi.com'
if (!container) {
document.body.style.overflow = 'hidden'
}
let iframeElement = document.createElement('iframe')
iframeElement.setAttribute('allow', 'web-share; clipboard-write;')
const productType = config.operation || config.product || 'Atomic'
iframeElement.setAttribute('title', `${productType} Interface`)
iframeElement.setAttribute('aria-label', `${productType} Interface`)
iframeElement.src = `${origin}/initialize/${btoa(
JSON.stringify({
inSdk: true,
platform: {
name: 'browser',
sdkVersion: '3.0.11',
systemVersion: `${navigator.platform}-${
navigator.vendor ?? 'unknown'
}`
},
...config
})
)}`
const baseStyles = [
{ width: '100%' },
{ height: '100%' },
{ 'z-index': '888888888' },
{ 'border-width': '0' },
{ 'overflow-x': 'hidden' },
{ 'overflow-y': 'auto' }
]
const modalStyles = [
{ position: 'fixed' },
{ top: '0' },
{ left: '0' },
{ right: '0' },
{ bottom: '0' }
]
const styles = [...baseStyles, ...(container ? [] : modalStyles)]
iframeElement.id = 'atomic-transact-iframe'
iframeElement.style.cssText = styles
.map((style) =>
Object.entries(style)
.map(([key, value]) => `${key}: ${value}; `)
.join('')
)
.join('')
.trim()
if (container) {
const containerElement = document.querySelector(container)
if (containerElement) {
containerElement.appendChild(iframeElement)
} else {
throw new Error(`No container found for "${container}"`)
}
} else {
document.body.appendChild(iframeElement)
}
atomicIframeEventListener = _handleIFrameEvent({
origin,
onInteraction,
onDataRequest,
onFinish,
onClose,
onOpenUrl
})
window.addEventListener('message', atomicIframeEventListener)
return {
close: () => _removeTransact()
}
}
}
function _handleIFrameEvent({
origin,
onInteraction,
onFinish,
onClose,
onDataRequest,
onOpenUrl
}) {
return (event) => {
if (origin !== event.origin) return
const { payload, event: eventName } = event.data
switch (eventName) {
case 'atomic-transact-close':
onClose(payload)
_removeTransact()
break
case 'atomic-transact-finish':
onFinish(payload)
_removeTransact()
break
case 'atomic-transact-interaction':
onInteraction(payload)
break
case 'atomic-transact-data-request':
onDataRequest(payload)
break
case 'atomic-transact-open-url':
if (onOpenUrl && typeof onOpenUrl === 'function') {
onOpenUrl({url: payload.url})
} else {
const url = new URL(payload.url)
if ('https:' === url.protocol)
window.open(payload.url, '_blank')
}
break
default:
console.log('Unhandled postMessage Event', eventName)
}
}
}
function _removeTransact() {
const iframeElement = document.querySelector('#atomic-transact-iframe')
window.removeEventListener('message', atomicIframeEventListener)
if (iframeElement?.parentNode !== document.body) return
document.body.style.removeProperty('overflow')
document.body.removeChild(iframeElement)
}
if (typeof exports !== 'undefined') {
exports.Product = atomicProduct
exports.Atomic = atomicSDK
} else {
window.Product = atomicProduct
window.Atomic = atomicSDK
}