import {StripeOnramp, StripeOnrampConstructor} from '../types'; export type LoadStripeOnramp = ( ...args: Parameters ) => Promise; // `_VERSION` will be rewritten by `@rollup/plugin-replace` as a string literal // containing the package.json version declare const _VERSION: string; const ONRAMP_URL = 'https://crypto-js.stripe.com/crypto-onramp-outer.js'; export const findScript = (): HTMLScriptElement | null => { const scripts = document.querySelectorAll( `script[src^="${ONRAMP_URL}"]` ); for (let i = 0; i < scripts.length; i++) { const script = scripts[i]; if (ONRAMP_URL !== script.src) { continue; } return script; } return null; }; const injectScript = (): HTMLScriptElement => { const script = document.createElement('script'); script.src = ONRAMP_URL; const headOrBody = document.head || document.body; if (!headOrBody) { throw new Error( 'Expected document.body not to be null. Stripe Crypto requires a element.' ); } headOrBody.appendChild(script); return script; }; const registerWrapper = (stripe: any, startTime: number): void => { // TODO(forestfang): we do not have a mechanism to track metrics here yet if (!stripe || !stripe._registerWrapper) { return; } stripe._registerWrapper({ name: 'crypto-js', version: _VERSION, startTime, }); }; let stripePromise: Promise | null = null; export const loadScript = (): Promise => { // Ensure that we only attempt to load Stripe.js at most once if (stripePromise !== null) { return stripePromise; } stripePromise = new Promise((resolve, reject) => { if (typeof window === 'undefined') { // Resolve to null when imported server side. This makes the module // safe to import in an isomorphic code base. resolve(null); return; } if (window.StripeOnramp) { resolve(window.StripeOnramp); return; } try { let script = findScript(); if (!script) { script = injectScript(); } script.addEventListener('load', () => { if (window.StripeOnramp) { resolve(window.StripeOnramp); } else { reject(new Error('StripeOnramp not available')); } }); script.addEventListener('error', () => { reject(new Error('Failed to load StripeOnramp')); }); } catch (error) { reject(error); return; } }); return stripePromise; }; export const initStripeOnramp = ( maybeStripeOnramp: StripeOnrampConstructor | null, args: Parameters, startTime: number ): StripeOnramp | null => { if (maybeStripeOnramp === null) { return null; } const stripeOnramp = maybeStripeOnramp.apply(undefined, args); registerWrapper(stripeOnramp, startTime); return stripeOnramp; };