Skip to content

Commit

Permalink
ref: setup drand client
Browse files Browse the repository at this point in the history
  • Loading branch information
RasenGUY committed Nov 26, 2023
1 parent 05f488c commit 8b5414b
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 52 deletions.
69 changes: 38 additions & 31 deletions src/common/FloatingOrbs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,43 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { FloatingOrbContainer, FloatingOrbBlurContainer } from './types';
import { useLayoutEffect, useRef } from 'react';
import { FloatingOrbContainer, FloatingOrbBlurContainer, FloatingOrbBlurContainerWithoutBackdrop, Orb } from './types';
import { gsap, Sine } from 'gsap';
import "twin.macro"

// interface FloatingOrbsProps {}

export const FloatingOrbs = () => (
<FloatingOrbContainer>
<FloatingOrbBlurContainer></FloatingOrbBlurContainer>
<div tw="relative flex justify-center items-center w-full h-full">
<div
tw="
dark:bg-[#C836E0]
pointer-events-none
absolute w-[350px] h-[350px]
rounded-[100%]
translate-x-[5rem] translate-y-[5rem] z-[-27]"
></div>
<div tw="
dark:bg-[#B80D57]
pointer-events-none
absolute
w-[350px]
h-[350px]
rounded-[100%]
translate-x-[-15rem] translate-y-[5rem] z-[-26]
"></div>
<div tw="
dark:bg-oranjo
pointer-events-none
absolute w-[350px] h-[350px] rounded-[100%]
translate-x-[15rem] translate-y-[-2.5rem] z-[-25]"></div>
export const FloatingOrbs: React.FC<React.AllHTMLAttributes<HTMLDivElement> & React.Attributes> = ({ children, ...props}: React.AllHTMLAttributes<HTMLDivElement> & React.Attributes) => {
const orbContainerRef = useRef<any>(null);

useLayoutEffect(() => {
const context = gsap.context(() => {
const tl = gsap.timeline();
const duration = 5;
const orbs = orbContainerRef.current.querySelectorAll('.orb');
tl.repeatDelay(0.25);
tl.fromTo(orbs[0], { scale: 1.1, rotate: '0deg', x: "-=5rem", y: "+=3rem" }, { scale: 1.05 , rotate: '180deg', x: "+=3rem", y: "-=5rem", repeat: -1, yoyo: true, duration, ease: Sine.easeInOut }, 'start')
tl.fromTo(orbs[1], { scale: 1.05, rotate: '0deg', x: "-=3rem", y: "+=3rem" }, { scale: 1.1 , rotate: '180deg', x: "+=3rem", y: "-=3rem", repeat: -1, yoyo: true, duration, ease: Sine.easeInOut }, '<')
tl.fromTo(orbs[2], { scale: 1.2, rotate: '0deg', x: "-=3rem", y: "+=3rem" }, { scale: 1 , rotate: '180deg', x: "+=3rem", y: "-=6rem", repeat: -1, yoyo: true, duration, ease: Sine.easeInOut }, '<')
tl.yoyo(true);
}, orbContainerRef.current);
return () => context.revert();
});

return !children ? (
<FloatingOrbContainer tw="overflow-clip" {...props}>
<FloatingOrbBlurContainerWithoutBackdrop></FloatingOrbBlurContainerWithoutBackdrop>
<div tw="relative flex justify-center items-center w-full sm:w-[100vw] sm:h-[100vh]" ref={orbContainerRef}>
<Orb className="orb" tw="dark:bg-[#C836E0] translate-x-[5rem] translate-y-[5rem] z-[-28]"/>
<Orb className="orb" tw="dark:bg-[#B80D57] translate-x-[-15rem] translate-y-[5rem] z-[-27]"/>
<Orb className="orb" tw="dark:bg-oranjo translate-x-[15rem] translate-y-[-2.5rem] z-[-25] z-[-26]"/>
</div>
</FloatingOrbContainer>
)
</FloatingOrbContainer>
) : <FloatingOrbContainer tw="relative w-full h-full" {...props}>
<FloatingOrbBlurContainer tw="rounded-[inherit]"></FloatingOrbBlurContainer>
<div tw="absolute flex justify-center items-center w-full h-full overflow-clip rounded-[inherit]" ref={orbContainerRef}>
<Orb className="orb" tw="dark:bg-[#C836E0] translate-x-[5rem] translate-y-[5rem] z-[-28]"/>
<Orb className="orb" tw="dark:bg-[#B80D57] translate-x-[-15rem] translate-y-[5rem] z-[-27]"/>
<Orb className="orb" tw="dark:bg-oranjo translate-x-[15rem] translate-y-[-2.5rem] z-[-25] z-[-26]"/>
</div>
{children}
</FloatingOrbContainer>
}

25 changes: 21 additions & 4 deletions src/common/FloatingOrbs/types.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
import tw, {styled} from 'twin.macro';

export const FloatingOrbContainer = styled.div`
${tw`absolute top-0 right-0 w-full h-full z-[-20] flex justify-center items-center`}
${tw`sm:mt-[-5rem] absolute top-0 right-0 w-full h-full z-[-51] flex justify-center items-center`}
overflow: clip;
`
export const FloatingOrbBlurContainer = styled.div`
content: '';
display: block;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: z-[-21];
${tw`backdrop-blur-[80px]`}
${tw`bg-pretu bg-opacity-[0.3]`}
${tw` z-[-21] backdrop-blur-[80px]`}
`

export const FloatingOrbBlurContainerWithoutBackdrop = styled.div`
content: '';
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
${tw`z-[-21] bg-pretu bg-opacity-[0.01]`}
-webkit-overflow: clip;
`

export const Orb = styled.div`
${tw`pointer-events-none absolute w-[350px] h-[350px] rounded-[100%] blur-[75px]`}
filter: blur(75px);
-webkit-filter: blur(75px);
`
3 changes: 1 addition & 2 deletions src/components/CreateGameCard/CreateCoinFlipGameCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ export const CreateCoinFlipGameCard = ({
ref={formRef}
>
<ToggleCoinFlipSides currentCoinSide={currentCoinSide} setCurrentCoinSide={setCurrentCoinSide} tw="mb-[32px]" />

<CreateGameCardContainer {...rest} tw="dark:bg-[#282828] rounded-[10px]">
<CreateGameCardContainer {...rest}>
{/* badge selection */}
<ToggleWagerBadge currentCurrencyType={currentCurrencyType} setCurrentCurrencyType={setCurrentCurrencyType} />
<div >
Expand Down
12 changes: 6 additions & 6 deletions src/components/CreateGameCard/CreateDiceGameCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { ArrowDownIcon, StarLoaderIcon } from '../../assets/icons';
import tw from 'twin.macro';
import { useForm } from 'react-hook-form';
import { useBalance } from 'wagmi';
import { useNavigateTo, useWegaStore, useCreateGameParams } from '../../hooks';
import { useNavigateTo, useWegaStore, useCreateGameParams, useTokenUSDValue } from '../../hooks';
import { useCreateGameMutation } from '../../containers/App/api';
import {
useCreateWagerAndDepositMutation,
Expand Down Expand Up @@ -69,7 +69,6 @@ export const CreateDiceGameCard = ({
const [currentWagerType] = useState<AllPossibleWagerTypes>(wagerType);
const [currentCurrencyType, setCurrentCurrencyType] = useState<AllPossibleCurrencyTypes>(currencyType);
const {revealed, triggerRevealAnimation} = useFormReveal(false, formRef, detailsBlock);

const { register, formState: { errors }, watch, handleSubmit, setValue } = useForm({
mode: 'onChange',
resolver: joiResolver(createGameSchema('wager')) ,
Expand All @@ -78,6 +77,7 @@ export const CreateDiceGameCard = ({
wager: 1
}
});
const wagerUSDValue = useTokenUSDValue(currentCurrencyType, watch('wager'));

// approval for allowance
const isWagerApproved = (allowance: number, wagerAmount: number) => allowance >= wagerAmount;
Expand All @@ -91,7 +91,6 @@ export const CreateDiceGameCard = ({
const { data: userWagerBalance, isLoading: isWagerbalanceLoading } = useBalance({
address: wallet?.address as HexishString,
token: tokenAddress,
enabled: false,
cacheTime: 60_000,
onError(error) {
console.log('Error', error)
Expand Down Expand Up @@ -165,7 +164,7 @@ export const CreateDiceGameCard = ({
onSubmit={handleSubmit(handleCreateGameClick)}
ref={formRef}
>
<CreateGameCardContainer {...rest} tw="dark:bg-[#282828] rounded-[10px]">
<CreateGameCardContainer {...rest}>
{/* badge selection */}
<ToggleWagerBadge currentCurrencyType={currentCurrencyType} setCurrentCurrencyType={setCurrentCurrencyType} />

Expand All @@ -180,9 +179,10 @@ export const CreateDiceGameCard = ({
name="wager"
render={({ message }) => <NormalText tw="text-[#E11D48]">{message}</NormalText> }
/>
<NormalText tw="dark:text-shinishi">00,00 USD</NormalText>
{/* should receive wager amount as input */}
<NormalText tw="dark:text-shinishi">{wagerUSDValue.loading ? 'loading...' : wagerUSDValue.value} USD</NormalText>
<SmallText> Balance: {
isWagerbalanceLoading ? "Retrieving balance..." : userWagerBalance ? userWagerBalance?.formatted + ' ' + userWagerBalance?.symbol : 0
isWagerbalanceLoading ? "Retrieving balance..." : userWagerBalance ? userWagerBalance?.formatted : String(0)
} </SmallText>
{/* useBalance from wagmi can be used here */}
</div>
Expand Down
1 change: 0 additions & 1 deletion src/components/CreateGameCard/apiSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ appApiSlice.enhanceEndpoints({
addTagTypes: ['Games'],
endpoints: { createGame: { invalidatesTags: [ { type: 'Games', id: 'LIST' } ]} }
});

export const { useCreateGameMutation } = createGameApiSlice;
3 changes: 1 addition & 2 deletions src/components/CreateGameCard/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const CreateGameCardContainer = styled.div`
flex-direction: column;
align-items: center;
gap: 32px;
${tw`dark:bg-[#282828] rounded-[10px] border border-[2px] border-[#343434]`}
`

export const InputBox = styled.input`
Expand All @@ -16,9 +17,7 @@ export const InputBox = styled.input`
line-height: 68px;
${tw`bg-inherit focus:outline-none`}
text-align: center;
-moz-appearance: textfield;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export { useWegaStore } from './useWegaStore';
export { useBlockchainApiHooks } from './useBlockchainApiHooks';
export { useNavigateTo } from './useNavigateTo';
export { useFirebaseData } from './useFirebaseData';
export { useCreateGameParams } from './useCreateGameParams';
export { useCreateGameParams } from './useCreateGameParams';
export { useTokenUSDValue } from './useTokenUSDValue';
10 changes: 10 additions & 0 deletions src/hooks/useTokenUSDValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { cryptoComparePriceApi } from "../utils/price"
import { useAsync } from 'react-use';
import { AllPossibleCurrencyTypes } from "../models";
export function useTokenUSDValue(token: AllPossibleCurrencyTypes, amount: number) {
const price = useAsync(async () => {
const price = Number(await cryptoComparePriceApi.fetchUsdPriceOf(token));
return parseFloat(String(amount * price)).toFixed(2);
}, [token, amount]);
return price;
}
70 changes: 70 additions & 0 deletions src/libs/drand/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// import { useLocalStorage } from 'react-use'
import { convertBytesToNumber } from '../../utils'
type DrandMeta = { chainHash: string; round: number; signature: string; randomness: bigint;}
interface IDrandClient {
getRandomNumber(): Promise<DrandMeta>;
getLastRequestedDrandMeta(): string | null;
// eslint-disable-next-line no-unused-vars
setDrandMeta(drandMeta: DrandMeta): void;
}

class DrandClient implements IDrandClient {
private metaStorageKey = 'drand_meta'
private baseUrl = 'https://api.drand.sh';
private fetchSettings = {
headers: {
'Access-Control-Allow-Origin': '*'
},
credentials: 'same-origin' as RequestCredentials,
cache: 'no-cache' as RequestCache
}
getLastRequestedDrandMeta() {
return JSON.parse(localStorage.getItem(this.metaStorageKey) as string) || null;
};
setDrandMeta(drandMeta: DrandMeta){
localStorage.setItem(this.metaStorageKey, JSON.stringify(drandMeta));
}
async getRandomNumber(): Promise<DrandMeta> {
const meta = this.getLastRequestedDrandMeta();
if(meta){
const newRound = meta.round++;
const data = await this.fetchDrand(meta.chainHash, newRound);
this.setDrandMeta(data)
return data;
} else {
const data = await this.fetchDrand(meta.chainHash);
this.setDrandMeta(data);
return data;
}
}

async fetchDrand(lastChainHash: string, lastRound?: number){
let fulfilled = false;
let result: DrandMeta = {
round: 0,
randomness: 0n,
signature: "",
chainHash: lastChainHash
}
while (!fulfilled) {
const res = await fetch(this.parseFetchUrl(lastChainHash, lastRound), this.fetchSettings);
const resBody = await res.text();
const { randomness, round, signature } = JSON.parse(resBody);
// set fulfilled to false;
if(randomness || round || signature) {
result = Object.assign(result, {
round,
randomness: convertBytesToNumber(randomness),
signature: signature,
chainHash: lastChainHash,
})
fulfilled = true;
}
}
return result;
}
parseFetchUrl(chainHash: string, round?: number): string {
return this.baseUrl.concat(`${chainHash}/public/${round ? round : 'latest'}`);
}
}
export const drandClient = new DrandClient();
4 changes: 3 additions & 1 deletion src/models/currency.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// eslint-disable-next-line no-unused-vars
export enum CurrencyTypesEnum { USDC, USDT };
export enum CurrencyTypesEnum { USDC, USDT, USD };
export const CurrencyTypes = {
[CurrencyTypesEnum.USDC]: 'USDC',
[CurrencyTypesEnum.USDT]: 'USDT',
[CurrencyTypesEnum.USD]: 'USD',
} as const;

export type AllPossibleCurrencyTypes = typeof CurrencyTypes[keyof typeof CurrencyTypes];
14 changes: 12 additions & 2 deletions src/utils/ethers-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { parseEther, BigNumberish, Interface } from "ethers";
import {
parseEther,
BigNumberish,
Interface,
toBigInt,
solidityPackedSha256
} from "ethers";
import { Player } from '../models'

export function parseIntFromBigNumber(val: BigNumberish | number) {
Expand Down Expand Up @@ -32,4 +38,8 @@ export function isGameCreator(
return true;
}
return false;
}
}

export function convertBytesToNumber(bytes: string): bigint {
return toBigInt(solidityPackedSha256(['bytes'],["0x".concat(bytes)]));
}
7 changes: 5 additions & 2 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export {
miniWalletAddress,
toBigIntInWei,
parseTopicDataFromEventLog,
interfaceIdFromAbi
interfaceIdFromAbi,
convertBytesToNumber
} from './ethers-helpers.ts'
export { deployed } from './deployment.ts'
export { toastSettings } from './toast.ts'
Expand All @@ -22,4 +23,6 @@ export {
wegaErc20EscrowConfig,
wegaGameControllerConfig,
wegaRandomizerControllerConfig
} from './abis.ts'
} from './abis.ts'

export { cryptoComparePriceApi } from './price.ts'
24 changes: 24 additions & 0 deletions src/utils/price.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AllPossibleCurrencyTypes } from "../models";

interface IPriceAPI {
// eslint-disable-next-line no-unused-vars
fetchUsdPriceOf(token: AllPossibleCurrencyTypes): Promise<number>;
}

class CryptoComparePriceApi implements IPriceAPI {
private baseUrl: string = 'https://min-api.cryptocompare.com';
async fetchUsdPriceOf(token: AllPossibleCurrencyTypes) {
try {
const response = await fetch(this.parseUrlForUSDPriceFetch(token));
const data = await response.json();
return data.USD;
} catch (e) {
console.log(e);
}
};
parseUrlForUSDPriceFetch(token: AllPossibleCurrencyTypes): string {
return `${this.baseUrl}/data/price?fsym=${token}&tsyms=USD`
}
}
export const cryptoComparePriceApi = new CryptoComparePriceApi();

0 comments on commit 8b5414b

Please sign in to comment.