Skip to content

Commit

Permalink
Merge branch 'polygon-prototype-staging' into 58-dump-signed-transact…
Browse files Browse the repository at this point in the history
…ions-for-manual-resolution
  • Loading branch information
ebma committed Aug 8, 2024
2 parents 69c17c3 + bbfd121 commit 4e2498f
Show file tree
Hide file tree
Showing 18 changed files with 340 additions and 138 deletions.
27 changes: 27 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@
<title>Vortex</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />

<!-- Google Tag Manager -->
<script>
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-T8JZSLD8');
</script>
<!-- End Google Tag Manager -->

<link
href="https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,wght@0,400;0,600;0,700;1,400&family=Outfit:wght@400;600&display=swap"
rel="stylesheet"
Expand All @@ -18,6 +34,17 @@
</head>

<body style="background-color: #fff">
<!-- Google Tag Manager (noscript) -->
<noscript
><iframe
src="https://www.googletagmanager.com/ns.html?id=GTM-T8JZSLD8"
height="0"
width="0"
style="display: none; visibility: hidden"
></iframe
></noscript>
<!-- End Google Tag Manager (noscript) -->

<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
Expand Down
3 changes: 1 addition & 2 deletions signer-service/src/api/services/stellar.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const {
Networks,
Asset,
Memo,
Transaction,
Account,
} = require('stellar-sdk');
const { HORIZON_URL, BASE_FEE } = require('../../constants/constants');
Expand All @@ -31,7 +30,7 @@ async function buildCreationStellarTx(fundingSecret, ephemeralAccountId, maxTime
const fundingSequence = fundingAccount.sequence;
// add a setOption oeration in order to make this a 2-of-2 multisig account where the
// funding account is a cosigner
let createAccountTransaction = new TransactionBuilder(fundingAccount, {
const createAccountTransaction = new TransactionBuilder(fundingAccount, {
fee: BASE_FEE,
networkPassphrase: NETWORK_PASSPHRASE,
})
Expand Down
2 changes: 1 addition & 1 deletion src/components/ExchangeRate/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FC } from 'preact/compat';
import { InputTokenDetails, OutputTokenDetails } from '../../constants/tokenConfig';
import { UseTokenOutAmountResult } from '../../hooks/nabla/useTokenAmountOut';
import { FC } from 'preact/compat';

interface ExchangeRateProps {
fromToken?: InputTokenDetails;
Expand Down
7 changes: 6 additions & 1 deletion src/components/FeeCollapse/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import LocalGasStationIcon from '@mui/icons-material/LocalGasStation';
import Big from 'big.js';
import { roundDownToSignificantDecimals } from '../../helpers/parseNumbers';
import { OUTPUT_TOKEN_CONFIG, OutputTokenType } from '../../constants/tokenConfig';
import { useEventsContext } from '../../contexts/events';

const FEES_RATE = 0.05; // 0.5% fee rate

Expand All @@ -27,8 +28,12 @@ interface CollapseProps {

export const FeeCollapse: FC<CollapseProps> = ({ fromAmount, toAmount, toCurrency }) => {
const [isOpen, setIsOpen] = useState(false);
const { trackEvent } = useEventsContext();

const toggleIsOpen = () => setIsOpen((state) => !state);
const toggleIsOpen = () => {
trackEvent({ event: 'click_details' });
setIsOpen((state) => !state);
};

const outputToken = toCurrency ? OUTPUT_TOKEN_CONFIG[toCurrency] : undefined;

Expand Down
2 changes: 1 addition & 1 deletion src/components/GenericEvent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React from 'preact/compat';

export enum EventStatus {
Success = 'success',
Expand Down
8 changes: 4 additions & 4 deletions src/components/Nabla/useSwapForm.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { yupResolver } from '@hookform/resolvers/yup';
import Big from 'big.js';
import { useCallback, useMemo, useState } from 'preact/compat';
import { Resolver, useForm, useWatch } from 'react-hook-form';
import { useState, useCallback, useMemo } from 'preact/compat';
import { yupResolver } from '@hookform/resolvers/yup';

import { INPUT_TOKEN_CONFIG, InputTokenType, OUTPUT_TOKEN_CONFIG, OutputTokenType } from '../../constants/tokenConfig';
import { storageKeys } from '../../constants/localStorage';
import { INPUT_TOKEN_CONFIG, InputTokenType, OUTPUT_TOKEN_CONFIG, OutputTokenType } from '../../constants/tokenConfig';
import { debounce } from '../../helpers/function';
import schema, { SwapFormValues } from './schema';
import { storageService } from '../../services/storage/local';
import schema, { SwapFormValues } from './schema';

interface SwapSettings {
from: string;
Expand Down
64 changes: 36 additions & 28 deletions src/components/NumericInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Input } from 'react-daisyui';
import { UseFormRegisterReturn } from 'react-hook-form';
import { useEventsContext } from '../../contexts/events';

export function exceedsMaxDecimals(value: unknown, maxDecimals: number) {
if (value === undefined || value === null) return true;
Expand Down Expand Up @@ -53,31 +54,38 @@ export const NumericInput = ({
autoFocus,
disabled,
disableStyles = false,
}: NumericInputProps) => (
<div className={disableStyles ? 'flex-grow' : 'flex-grow text-black font-outfit'}>
<Input
autocomplete="off"
autocorrect="off"
autocapitalize="none"
className={
disableStyles
? 'border-0 bg-transparent focus:outline-none px-4 ' + additionalStyle
: 'input-ghost w-full text-lg pl-2 focus:outline-none text-accent-content ' + additionalStyle
}
minlength="1"
onKeyPress={(e: KeyboardEvent) => handleOnKeyPress(e, maxDecimals)}
onInput={handleOnInput}
pattern="^[0-9]*[.,]?[0-9]*$"
placeholder="0.0"
readOnly={readOnly}
spellcheck="false"
step="any"
type="text"
inputmode="decimal"
value={defaultValue}
autoFocus={autoFocus}
disabled={disabled}
{...register}
/>
</div>
);
}: NumericInputProps) => {
const { trackEvent } = useEventsContext();

return (
<div className={disableStyles ? 'flex-grow' : 'flex-grow text-black font-outfit'}>
<Input
autocomplete="off"
autocorrect="off"
autocapitalize="none"
className={
disableStyles
? 'border-0 bg-transparent focus:outline-none px-4 ' + additionalStyle
: 'input-ghost w-full text-lg pl-2 focus:outline-none text-accent-content ' + additionalStyle
}
minlength="1"
onKeyPress={(e: KeyboardEvent) => handleOnKeyPress(e, maxDecimals)}
onInput={(e: KeyboardEvent) => {
trackEvent({ event: 'amount_type' });
handleOnInput(e);
}}
pattern="^[0-9]*[.,]?[0-9]*$"
placeholder="0.0"
readOnly={readOnly}
spellcheck="false"
step="any"
type="text"
inputmode="decimal"
value={defaultValue}
autoFocus={autoFocus}
disabled={disabled}
{...register}
/>
</div>
);
};
61 changes: 61 additions & 0 deletions src/components/SigningBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import AccountBalanceWalletOutlinedIcon from '@mui/icons-material/AccountBalanceWalletOutlined';
import { Progress } from 'react-daisyui';
import { FC } from 'preact/compat';

import { SigningPhase } from '../../hooks/useMainProcess';

const progressValues: Record<SigningPhase, string> = {
started: '25',
approved: '50',
signed: '75',
finished: '100',
};

function getProgressValue(step: SigningPhase): string {
return progressValues[step] || '0';
}

function getSignatureNumber(step: SigningPhase): string {
return step === 'started' ? '1' : '2';
}

interface SigningBoxProps {
step?: SigningPhase;
}

export const SigningBox: FC<SigningBoxProps> = ({ step }) => {
if (!step) return <></>;
if (step !== 'started' && step !== 'approved' && step !== 'signed') return <></>;

return (
<section className="toast toast-end">
<div className="shadow-2xl">
<header className="bg-pink-500 rounded-t">
<h1 className="w-full py-2 text-center text-white">Action Required</h1>
</header>
<main className="px-8 bg-white">
<div className="flex items-center justify-center">
<div className="flex items-center justify-center w-10 h-10 border rounded-full border-primary">
<AccountBalanceWalletOutlinedIcon className="text-primary" />
</div>
<div className="mx-4 my-5 text-xs">
<p>Please sign the transaction in</p>
<p>your connected wallet to proceed</p>
</div>
</div>
<div className="w-full mb-2.5">
<Progress
value={getProgressValue(step)}
max="100"
className="h-4 bg-white border progress-primary border-primary"
/>
</div>
</main>
<footer className="flex items-center justify-center bg-[#5E88D5] text-white rounded-b">
<span className="loading loading-spinner loading-sm"></span>
<p className="ml-2.5 my-2 text-xs">Waiting for signature {getSignatureNumber(step)}/2</p>
</footer>
</div>
</section>
);
};
121 changes: 121 additions & 0 deletions src/contexts/events.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { createContext } from 'preact';
import { PropsWithChildren, useCallback, useContext, useEffect, useRef, useState } from 'preact/compat';
import { useAccount } from 'wagmi';
import { INPUT_TOKEN_CONFIG, OUTPUT_TOKEN_CONFIG } from '../constants/tokenConfig';
import { OfframpingState } from '../services/offrampingFlow';

declare global {
interface Window {
dataLayer: Record<string, any>[];
}
}

const UNIQUE_EVENT_TYPES = ['amount_type', 'click_details', 'click_support'];

export interface AmountTypeEvent {
event: `amount_type`;
}

export interface ClickDetailsEvent {
event: 'click_details';
}

export interface WalletConnectEvent {
event: 'wallet_connect';
wallet_action: 'connect' | 'disconnect' | 'change';
}

export interface TransactionEvent {
event: 'transaction_confirmation' | 'kyc_completed' | 'transaction_success' | 'transaction_failure';
from_asset: string;
to_asset: string;
from_amount: string;
to_amount: string;
}

export interface ClickSupportEvent {
event: 'click_support';
transaction_status: 'success' | 'failure';
}

export type TrackableEvent =
| AmountTypeEvent
| ClickDetailsEvent
| WalletConnectEvent
| TransactionEvent
| ClickSupportEvent;

type EventType = TrackableEvent['event'];

type UseEventsContext = ReturnType<typeof useEvents>;
const useEvents = () => {
const [_, setTrackedEventTypes] = useState<Set<EventType>>(new Set());

const previousAddress = useRef<`0x${string}` | undefined>(undefined);
const { address } = useAccount();

const trackEvent = useCallback(
(event: TrackableEvent) => {
setTrackedEventTypes((trackedEventTypes) => {
if (UNIQUE_EVENT_TYPES.includes(event.event)) {
if (trackedEventTypes.has(event.event)) {
return trackedEventTypes;
} else {
trackedEventTypes = new Set(trackedEventTypes);
trackedEventTypes.add(event.event);
}
}
console.log('Push data layer', event);

window.dataLayer.push(event);

return trackedEventTypes;
});
},
[setTrackedEventTypes],
);

useEffect(() => {
const wasConnected = previousAddress.current !== undefined;
const isConnected = address !== undefined;

if (!isConnected) {
trackEvent({ event: 'wallet_connect', wallet_action: 'disconnect' });
} else {
trackEvent({ event: 'wallet_connect', wallet_action: wasConnected ? 'change' : 'connect' });
}

previousAddress.current = address;
}, [address]);

return {
trackEvent,
};
};

const Context = createContext<UseEventsContext | undefined>(undefined);

export const useEventsContext = () => {
const contextValue = useContext(Context);
if (contextValue === undefined) {
throw new Error('Context must be inside a Provider');
}

return contextValue;
};

export function EventsProvider({ children }: PropsWithChildren) {
const useEventsResult = useEvents();

return <Context.Provider value={useEventsResult}>{children}</Context.Provider>;
}

export function createTransactionEvent(type: TransactionEvent['event'], state: OfframpingState) {
return {
event: type,
from_asset: INPUT_TOKEN_CONFIG[state.inputTokenType].assetSymbol,
to_asset: OUTPUT_TOKEN_CONFIG[state.outputTokenType].stellarAsset.code.string,
from_amount: state.inputAmount.units,
to_amount: state.outputAmount.units,
};
}
Loading

0 comments on commit 4e2498f

Please sign in to comment.