diff --git a/web/package.json b/web/package.json
index 33cebe9e5..ef2fc4465 100644
--- a/web/package.json
+++ b/web/package.json
@@ -43,11 +43,11 @@
"@eversdk/appkit": "^0.3.8",
"@eversdk/core": "^1.44.2",
"@eversdk/lib-web": "^1.44.2",
- "@fortawesome/fontawesome-svg-core": "^6.1.1",
- "@fortawesome/free-brands-svg-icons": "^6.1.1",
- "@fortawesome/free-regular-svg-icons": "^6.1.1",
- "@fortawesome/free-solid-svg-icons": "^6.1.1",
- "@fortawesome/react-fontawesome": "^0.1.18",
+ "@fortawesome/fontawesome-svg-core": "^6.4.2",
+ "@fortawesome/free-brands-svg-icons": "^6.4.2",
+ "@fortawesome/free-regular-svg-icons": "^6.4.2",
+ "@fortawesome/free-solid-svg-icons": "^6.4.2",
+ "@fortawesome/react-fontawesome": "^0.1.19",
"@headlessui/react": "^1.6.0",
"@monaco-editor/react": "^4.4.6",
"@mui/icons-material": "^5.8.4",
@@ -58,7 +58,7 @@
"@wysimark/react": "^2.2.15",
"apexcharts": "^3.37.0",
"buffer": "^6.0.3",
- "classnames": "^2.3.1",
+ "classnames": "^2.3.2",
"copy-to-clipboard": "^3.3.3",
"crypto-js": "^4.1.1",
"diff": "^5.1.0",
diff --git a/web/src/utils.ts b/web/src/utils.ts
index 9d1f73eff..33d8f1b5e 100644
--- a/web/src/utils.ts
+++ b/web/src/utils.ts
@@ -20,10 +20,40 @@ export const roundNumber = (value: number | string, precision: number = 5) => {
return Math.round(floatvalue * multiplier) / multiplier
}
-export const getDurationDelta = (time: number) => {
+export const getDurationDelta = (time: number, format: string) => {
const ms = moment(time).diff(moment())
const delta = moment.duration(ms)
- return `${delta.days()}d ${delta.hours()}h ${delta.minutes()}m`
+
+ const parsed = []
+ while (format) {
+ const sindex = format.indexOf('[')
+ const eindex = format.indexOf(']')
+ const group = format.slice(sindex + 1, eindex)
+ format = format.slice(eindex + 1)
+
+ const nindex = format.indexOf('[')
+ const delimiter = format.slice(0, nindex)
+ format = format.slice(nindex)
+
+ parsed.push([group, delimiter])
+ }
+
+ const filled = parsed.map(([group, delimiter]) => {
+ const [sign, label] = group.split(':').concat('')
+
+ let value = 0
+ if (sign === 'd') {
+ value = delta.days()
+ } else if (sign === 'h') {
+ value = delta.hours()
+ } else if (sign === 'm') {
+ value = delta.minutes()
+ } else if (sign === 's') {
+ value = delta.seconds()
+ }
+ return `${value}${label}${delimiter}`
+ })
+ return filled.join('')
}
export const sleep = (ms: number = 0) => {
@@ -134,6 +164,10 @@ export const fromBigint = (number: bigint, decimals: number) => {
// 001234 -> '001234'
const fraction = zeroPaddedValue.slice(-decimals).replace(/\.?0+$/, '')
+ if (integer === '' && fraction === '') {
+ return '0'
+ }
+
if (integer === '') {
return `0.${fraction}`
}
diff --git a/web/src/v1.0.0/components/DaoEvent/Progress.tsx b/web/src/v1.0.0/components/DaoEvent/Progress.tsx
index d676f35fa..45cbcd0f1 100644
--- a/web/src/v1.0.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v1.0.0/components/DaoEvent/Progress.tsx
@@ -62,7 +62,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
? `Closed at ${new Date(
time.completed || time.finish,
).toLocaleDateString()}`
- : `Ends in ${getDurationDelta(time.finish)}`}
+ : `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`}
)
diff --git a/web/src/v1.0.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v1.0.0/pages/DaoEvent/DaoEvent.tsx
index ada5199db..a5ed43170 100644
--- a/web/src/v1.0.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v1.0.0/pages/DaoEvent/DaoEvent.tsx
@@ -128,7 +128,7 @@ const DaoEventPageInner = (props: { address: string }) => {
End date
- {getDurationDelta(event.time.finish)}
+ {getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')}
diff --git a/web/src/v1.0.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v1.0.0/pages/DaoEventList/components/ListItem.tsx
index 621b78cf7..a3e0510e5 100644
--- a/web/src/v1.0.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v1.0.0/pages/DaoEventList/components/ListItem.tsx
@@ -99,7 +99,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v2.0.0/components/DaoEvent/Progress.tsx b/web/src/v2.0.0/components/DaoEvent/Progress.tsx
index 5d8cd0661..7beeadb0c 100644
--- a/web/src/v2.0.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v2.0.0/components/DaoEvent/Progress.tsx
@@ -68,7 +68,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
time.completed || time.finish,
).toLocaleDateString()}`
: time.finish > 0
- ? `Ends in ${getDurationDelta(time.finish)}`
+ ? `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`
: 'Review required'}
diff --git a/web/src/v2.0.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v2.0.0/pages/DaoEvent/DaoEvent.tsx
index b02afe0f1..d3993e1b1 100644
--- a/web/src/v2.0.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v2.0.0/pages/DaoEvent/DaoEvent.tsx
@@ -151,7 +151,10 @@ const DaoEventPageInner = (props: { address: string }) => {
event.time.completed || event.time.finish,
).toLocaleDateString()
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(
+ event.time.finish,
+ '[d:d] [h:h] [m:m]',
+ )
: 'Review required'}
diff --git a/web/src/v2.0.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v2.0.0/pages/DaoEventList/components/ListItem.tsx
index 71c8f1bd7..331ee13f3 100644
--- a/web/src/v2.0.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v2.0.0/pages/DaoEventList/components/ListItem.tsx
@@ -115,7 +115,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v3.0.0/components/DaoEvent/Progress.tsx b/web/src/v3.0.0/components/DaoEvent/Progress.tsx
index 5d8cd0661..7beeadb0c 100644
--- a/web/src/v3.0.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v3.0.0/components/DaoEvent/Progress.tsx
@@ -68,7 +68,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
time.completed || time.finish,
).toLocaleDateString()}`
: time.finish > 0
- ? `Ends in ${getDurationDelta(time.finish)}`
+ ? `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`
: 'Review required'}
diff --git a/web/src/v3.0.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v3.0.0/pages/DaoEvent/DaoEvent.tsx
index d065d7d41..b67376939 100644
--- a/web/src/v3.0.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v3.0.0/pages/DaoEvent/DaoEvent.tsx
@@ -154,7 +154,10 @@ const DaoEventPageInner = (props: { address: string }) => {
event.time.completed || event.time.finish,
).toLocaleDateString()
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(
+ event.time.finish,
+ '[d:d] [h:h] [m:m]',
+ )
: 'Review required'}
diff --git a/web/src/v3.0.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v3.0.0/pages/DaoEventList/components/ListItem.tsx
index 71c8f1bd7..331ee13f3 100644
--- a/web/src/v3.0.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v3.0.0/pages/DaoEventList/components/ListItem.tsx
@@ -115,7 +115,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v4.0.0/components/DaoEvent/Progress.tsx b/web/src/v4.0.0/components/DaoEvent/Progress.tsx
index 5d8cd0661..7beeadb0c 100644
--- a/web/src/v4.0.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v4.0.0/components/DaoEvent/Progress.tsx
@@ -68,7 +68,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
time.completed || time.finish,
).toLocaleDateString()}`
: time.finish > 0
- ? `Ends in ${getDurationDelta(time.finish)}`
+ ? `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`
: 'Review required'}
diff --git a/web/src/v4.0.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v4.0.0/pages/DaoEvent/DaoEvent.tsx
index cee09b0a2..da77b0d01 100644
--- a/web/src/v4.0.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v4.0.0/pages/DaoEvent/DaoEvent.tsx
@@ -155,7 +155,10 @@ const DaoEventPageInner = (props: { address: string }) => {
event.time.completed || event.time.finish,
).toLocaleDateString()
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(
+ event.time.finish,
+ '[d:d] [h:h] [m:m]',
+ )
: 'Review required'}
diff --git a/web/src/v4.0.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v4.0.0/pages/DaoEventList/components/ListItem.tsx
index 71c8f1bd7..331ee13f3 100644
--- a/web/src/v4.0.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v4.0.0/pages/DaoEventList/components/ListItem.tsx
@@ -115,7 +115,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v5.0.0/components/DaoEvent/Progress.tsx b/web/src/v5.0.0/components/DaoEvent/Progress.tsx
index 5d8cd0661..7beeadb0c 100644
--- a/web/src/v5.0.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v5.0.0/components/DaoEvent/Progress.tsx
@@ -68,7 +68,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
time.completed || time.finish,
).toLocaleDateString()}`
: time.finish > 0
- ? `Ends in ${getDurationDelta(time.finish)}`
+ ? `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`
: 'Review required'}
diff --git a/web/src/v5.0.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v5.0.0/pages/DaoEvent/DaoEvent.tsx
index cee09b0a2..da77b0d01 100644
--- a/web/src/v5.0.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v5.0.0/pages/DaoEvent/DaoEvent.tsx
@@ -155,7 +155,10 @@ const DaoEventPageInner = (props: { address: string }) => {
event.time.completed || event.time.finish,
).toLocaleDateString()
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(
+ event.time.finish,
+ '[d:d] [h:h] [m:m]',
+ )
: 'Review required'}
diff --git a/web/src/v5.0.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v5.0.0/pages/DaoEventList/components/ListItem.tsx
index 71c8f1bd7..331ee13f3 100644
--- a/web/src/v5.0.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v5.0.0/pages/DaoEventList/components/ListItem.tsx
@@ -115,7 +115,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v5.1.0/components/DaoEvent/Progress.tsx b/web/src/v5.1.0/components/DaoEvent/Progress.tsx
index 5d8cd0661..7beeadb0c 100644
--- a/web/src/v5.1.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v5.1.0/components/DaoEvent/Progress.tsx
@@ -68,7 +68,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
time.completed || time.finish,
).toLocaleDateString()}`
: time.finish > 0
- ? `Ends in ${getDurationDelta(time.finish)}`
+ ? `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`
: 'Review required'}
diff --git a/web/src/v5.1.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v5.1.0/pages/DaoEvent/DaoEvent.tsx
index cee09b0a2..da77b0d01 100644
--- a/web/src/v5.1.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v5.1.0/pages/DaoEvent/DaoEvent.tsx
@@ -155,7 +155,10 @@ const DaoEventPageInner = (props: { address: string }) => {
event.time.completed || event.time.finish,
).toLocaleDateString()
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(
+ event.time.finish,
+ '[d:d] [h:h] [m:m]',
+ )
: 'Review required'}
diff --git a/web/src/v5.1.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v5.1.0/pages/DaoEventList/components/ListItem.tsx
index 71c8f1bd7..331ee13f3 100644
--- a/web/src/v5.1.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v5.1.0/pages/DaoEventList/components/ListItem.tsx
@@ -115,7 +115,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v6.0.0/components/DaoEvent/Progress.tsx b/web/src/v6.0.0/components/DaoEvent/Progress.tsx
index 5d8cd0661..7beeadb0c 100644
--- a/web/src/v6.0.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v6.0.0/components/DaoEvent/Progress.tsx
@@ -68,7 +68,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
time.completed || time.finish,
).toLocaleDateString()}`
: time.finish > 0
- ? `Ends in ${getDurationDelta(time.finish)}`
+ ? `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`
: 'Review required'}
diff --git a/web/src/v6.0.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v6.0.0/pages/DaoEvent/DaoEvent.tsx
index cee09b0a2..da77b0d01 100644
--- a/web/src/v6.0.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v6.0.0/pages/DaoEvent/DaoEvent.tsx
@@ -155,7 +155,10 @@ const DaoEventPageInner = (props: { address: string }) => {
event.time.completed || event.time.finish,
).toLocaleDateString()
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(
+ event.time.finish,
+ '[d:d] [h:h] [m:m]',
+ )
: 'Review required'}
diff --git a/web/src/v6.0.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v6.0.0/pages/DaoEventList/components/ListItem.tsx
index 71c8f1bd7..331ee13f3 100644
--- a/web/src/v6.0.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v6.0.0/pages/DaoEventList/components/ListItem.tsx
@@ -115,7 +115,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v6.1.0/components/DaoEvent/Progress.tsx b/web/src/v6.1.0/components/DaoEvent/Progress.tsx
index 5d8cd0661..7beeadb0c 100644
--- a/web/src/v6.1.0/components/DaoEvent/Progress.tsx
+++ b/web/src/v6.1.0/components/DaoEvent/Progress.tsx
@@ -68,7 +68,7 @@ const DaoEventProgressBar = (props: TEventProgressBarProps) => {
time.completed || time.finish,
).toLocaleDateString()}`
: time.finish > 0
- ? `Ends in ${getDurationDelta(time.finish)}`
+ ? `Ends in ${getDurationDelta(time.finish, '[d:d] [h:h] [m:m]')}`
: 'Review required'}
diff --git a/web/src/v6.1.0/hooks/l2.hooks.ts b/web/src/v6.1.0/hooks/l2.hooks.ts
index c5e8020d7..d536f3f76 100644
--- a/web/src/v6.1.0/hooks/l2.hooks.ts
+++ b/web/src/v6.1.0/hooks/l2.hooks.ts
@@ -7,9 +7,10 @@ import { AppConfig } from '../../appconfig'
import { appToastStatusSelector } from '../../store/app.state'
import { GoshError } from '../../errors'
import { useUser } from './user.hooks'
-import { fromBigint, toBigint, whileFinite } from '../../utils'
+import { fromBigint, setLockableInterval, toBigint, whileFinite } from '../../utils'
import { EL2Network, TL2TransferStatusItem, TL2User } from '../types/l2.types'
import { L2_COMISSION } from '../../constants'
+import { supabase } from '../../supabase'
export function useL2Transfer(options: { initialize?: boolean } = {}) {
const { initialize } = options
@@ -162,29 +163,30 @@ export function useL2Transfer(options: { initialize?: boolean } = {}) {
},
}
})
- } else if (values.from_amount && parseFloat(values.from_amount) > 0) {
+ } else if (values.from_amount && parseFloat(values.from_amount) >= 0) {
setData((state) => {
- // Subtract comission when ETH -> GOSH
- let to_amount = toBigint(
+ // Cast from_amount to BigInt
+ const from_amount = toBigint(
values.from_amount!,
state.networks[state.summary.from.network].decimals,
)
- if (state.summary.from.network === EL2Network.ETH) {
- to_amount = to_amount - to_amount / BigInt(L2_COMISSION)
+
+ // Calculate comission
+ const route = `${data.summary.from.network}:${data.summary.to.network}`
+ let comission = 0n
+ if (route === `${EL2Network.ETH}:${EL2Network.GOSH}`) {
+ comission = from_amount / BigInt(L2_COMISSION)
+ } else if (route === `${EL2Network.GOSH}:${EL2Network.ETH}`) {
+ comission = data.comissions[route]
}
+ // to.amount is calculated by useCallback with deps
return {
...state,
+ comissions: { ...state.comissions, [route]: comission },
summary: {
...state.summary,
from: { ...state.summary.from, amount: values.from_amount! },
- to: {
- ...state.summary.to,
- amount: fromBigint(
- to_amount,
- state.networks[state.summary.to.network].decimals,
- ),
- },
},
}
})
@@ -568,6 +570,36 @@ export function useL2Transfer(options: { initialize?: boolean } = {}) {
}))
}, [data.gosh.instance?.address])
+ const getWeb3Comission = useCallback(async () => {
+ try {
+ const { data, error } = await supabase.client
+ .from('l2_state')
+ .select()
+ .order('created_at', { ascending: false })
+ if (error) {
+ throw new GoshError('Get web3 comission', error.message)
+ }
+ if (!data.length) {
+ throw new GoshError('Get web3 comission', 'No data')
+ }
+
+ const row = data[0]
+ let comission = BigInt(row.current_approximate_elock_commissions)
+ comission += 21000n * BigInt(row.current_eth_gas_price)
+ comission /= BigInt(row.queued_burns_cnt + 1)
+
+ setData((state) => ({
+ ...state,
+ comissions: {
+ ...state.comissions,
+ [`${EL2Network.GOSH}:${EL2Network.ETH}`]: comission,
+ },
+ }))
+ } catch (e: any) {
+ console.warn(e.message)
+ }
+ }, [])
+
// Connect GOSH account
useEffect(() => {
if (initialize) {
@@ -609,7 +641,7 @@ export function useL2Transfer(options: { initialize?: boolean } = {}) {
}
}, [initialize, goshSubscribeCallback])
- // Subscribe ETH account/provider
+ // Subscribe web3 account/provider
useEffect(() => {
if (!initialize) {
return
@@ -631,6 +663,51 @@ export function useL2Transfer(options: { initialize?: boolean } = {}) {
}
}, [initialize, web3SubscribeCallback])
+ // Subscribe (periodic update) for web3 comission
+ useEffect(() => {
+ let interval: NodeJS.Timer
+ if (initialize) {
+ getWeb3Comission()
+ interval = setLockableInterval(async () => {
+ await getWeb3Comission()
+ }, 15000)
+ }
+
+ return () => {
+ clearInterval(interval)
+ }
+ }, [initialize, getWeb3Comission])
+
+ // Update to_amount by deps
+ useEffect(() => {
+ const { summary, comissions, networks } = data
+ const comission = comissions[`${summary.from.network}:${summary.to.network}`]
+ const from_amount = toBigint(
+ summary.from.amount,
+ networks[summary.from.network].decimals,
+ )
+ const to_amount = from_amount - comission
+
+ setData((state) => ({
+ ...state,
+ summary: {
+ ...state.summary,
+ to: {
+ ...state.summary.to,
+ amount: fromBigint(
+ to_amount > 0 ? to_amount : 0n,
+ networks[state.summary.to.network].decimals,
+ ),
+ },
+ },
+ }))
+ }, [
+ data.summary.from.network,
+ data.summary.to.network,
+ data.summary.from.amount,
+ data.comissions,
+ ])
+
return {
...data,
status,
diff --git a/web/src/v6.1.0/pages/DaoEvent/DaoEvent.tsx b/web/src/v6.1.0/pages/DaoEvent/DaoEvent.tsx
index 3cd13dcf5..f21e25461 100644
--- a/web/src/v6.1.0/pages/DaoEvent/DaoEvent.tsx
+++ b/web/src/v6.1.0/pages/DaoEvent/DaoEvent.tsx
@@ -159,7 +159,10 @@ const DaoEventPageInner = (props: { address: string }) => {
event.time.completed || event.time.finish,
).toLocaleDateString()
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(
+ event.time.finish,
+ '[d:d] [h:h] [m:m]',
+ )
: 'Review required'}
diff --git a/web/src/v6.1.0/pages/DaoEventList/components/ListItem.tsx b/web/src/v6.1.0/pages/DaoEventList/components/ListItem.tsx
index 71c8f1bd7..331ee13f3 100644
--- a/web/src/v6.1.0/pages/DaoEventList/components/ListItem.tsx
+++ b/web/src/v6.1.0/pages/DaoEventList/components/ListItem.tsx
@@ -115,7 +115,7 @@ const ListItem = (props: TListItemProps) => {
{event.status.completed
? 'Completed'
: event.time.finish > 0
- ? getDurationDelta(event.time.finish)
+ ? getDurationDelta(event.time.finish, '[d:d] [h:h] [m:m]')
: '-'}
diff --git a/web/src/v6.1.0/pages/L2/L2.tsx b/web/src/v6.1.0/pages/L2/L2.tsx
index cd7553f71..0ba615fa7 100644
--- a/web/src/v6.1.0/pages/L2/L2.tsx
+++ b/web/src/v6.1.0/pages/L2/L2.tsx
@@ -1,13 +1,14 @@
import { AnimatePresence, motion } from 'framer-motion'
import { useL2Transfer } from '../../hooks/l2.hooks'
import { CompleteStep, TransferStep, RouteStep, Breadcrumbs } from './components'
-import { fromBigint, shortString, roundNumber } from '../../../utils'
-import { useEffect } from 'react'
+import { fromBigint, shortString, roundNumber, getDurationDelta } from '../../../utils'
+import { useEffect, useState } from 'react'
import Alert from '../../../components/Alert'
import CopyClipboard from '../../../components/CopyClipboard'
import { useErrorBoundary, withErrorBoundary } from 'react-error-boundary'
import { EL2Network } from '../../types/l2.types'
import { Button } from '../../../components/Form'
+import moment from 'moment'
const motionProps = {
initial: { opacity: 0 },
@@ -16,12 +17,25 @@ const motionProps = {
transition: { duration: 0.25 },
}
+const getPayoutTime = () => {
+ const hours = [0, 3, 6, 9, 12, 15, 18, 21]
+ const moments = hours.map((h) => moment.utc({ hour: h, minute: 0, second: 0 }))
+ moments.push(moment.utc({ day: moment.utc().date() + 1, hour: 0, second: 0 }))
+
+ const now = moment()
+ const diffs = moments.map((m) => m.diff(now, 'seconds'))
+ const index = diffs.findIndex((diff) => diff > 0)
+ return moments[index]
+}
+
const L2PageInner = () => {
const { showBoundary } = useErrorBoundary()
- const { web3, gosh, networks, summary, step, reset, error, connectWeb3 } =
+ const { web3, gosh, comissions, networks, summary, step, reset, error, connectWeb3 } =
useL2Transfer({
initialize: true,
})
+ const [payout, setPayout] = useState(getPayoutTime())
+ const route = `${summary.from.network}:${summary.to.network}`
const getNetworkBalance = (network: string) => {
const floatstr = fromBigint(networks[network].balance, networks[network].decimals)
@@ -35,7 +49,10 @@ const L2PageInner = () => {
}, [error])
useEffect(() => {
+ const interval = setInterval(() => setPayout(getPayoutTime()), 1000)
+
return () => {
+ clearInterval(interval)
reset()
}
}, [])
@@ -196,6 +213,30 @@ const L2PageInner = () => {
+
+
+
+
Estimate comission
+
+ {fromBigint(
+ comissions[route],
+ networks[summary.to.network].decimals,
+ )}{' '}
+
+ {networks[summary.to.network].token}
+
+
+
+
+ {route === `${EL2Network.GOSH}:${EL2Network.ETH}` && (
+
+
Next payout
+
+ {getDurationDelta(payout, '[h:h] [m:m] [s:s]')}
+
+
+ )}
+
diff --git a/web/src/v6.1.0/pages/L2/components/RouteStep/AmountField.tsx b/web/src/v6.1.0/pages/L2/components/RouteStep/AmountField.tsx
index 741c007b5..cb0b38590 100644
--- a/web/src/v6.1.0/pages/L2/components/RouteStep/AmountField.tsx
+++ b/web/src/v6.1.0/pages/L2/components/RouteStep/AmountField.tsx
@@ -4,6 +4,7 @@ import { useL2Transfer } from '../../../../hooks/l2.hooks'
import { Button } from '../../../../../components/Form'
import classNames from 'classnames'
import { fromBigint, roundNumber } from '../../../../../utils'
+import { useRef } from 'react'
type TAmountFieldProps = {
network: string
@@ -15,7 +16,8 @@ type TAmountFieldProps = {
const AmountField = (props: TAmountFieldProps) => {
const { network, prefix, label, disabled, onChange } = props
- const { networks, setSummaryFormValues } = useL2Transfer()
+ const ref = useRef(null)
+ const { networks } = useL2Transfer()
const getNetworkBalance = (network: string) => {
const floatstr = fromBigint(networks[network].balance, networks[network].decimals)
@@ -23,12 +25,15 @@ const AmountField = (props: TAmountFieldProps) => {
}
const onMaxClick = () => {
- setSummaryFormValues({
- from_amount: fromBigint(
- networks[network].balance,
- networks[network].decimals,
- ),
- })
+ if (!ref.current) {
+ return
+ }
+
+ ref.current.value = fromBigint(
+ networks[network].balance,
+ networks[network].decimals,
+ )
+ onChange && onChange({ target: ref.current })
}
return (
@@ -41,6 +46,7 @@ const AmountField = (props: TAmountFieldProps) => {
readOnly={disabled}
disabled={disabled}
inputProps={{
+ ref: ref,
after: (
{networks[network].token}
diff --git a/web/src/v6.1.0/pages/L2/components/RouteStep/RouteStep.tsx b/web/src/v6.1.0/pages/L2/components/RouteStep/RouteStep.tsx
index ac9c5c856..ae19f7f0b 100644
--- a/web/src/v6.1.0/pages/L2/components/RouteStep/RouteStep.tsx
+++ b/web/src/v6.1.0/pages/L2/components/RouteStep/RouteStep.tsx
@@ -82,11 +82,11 @@ const RouteStep = () => {
from_network: summary.from.network,
from_user: summary.from.user,
from_wallet: summary.from.wallet,
- from_amount: summary.from.amount.toString(),
+ from_amount: summary.from.amount,
to_network: summary.to.network,
to_user: summary.to.user,
to_wallet: summary.to.wallet,
- to_amount: summary.to.amount.toString(),
+ to_amount: summary.to.amount,
}}
validationSchema={yup.object().shape({
from_network: yup.string().required(),
diff --git a/web/src/v6.1.0/store/l2.state.ts b/web/src/v6.1.0/store/l2.state.ts
index 2ba9c52f5..9972b54f9 100644
--- a/web/src/v6.1.0/store/l2.state.ts
+++ b/web/src/v6.1.0/store/l2.state.ts
@@ -13,6 +13,11 @@ export const l2TransferAtom = atom({
instance: null,
address: '',
},
+ comissions: {
+ [`${EL2Network.ETH}:${EL2Network.GOSH}`]: 0n,
+ [`${EL2Network.GOSH}:${EL2Network.ETH}`]: 0n,
+ [`${EL2Network.GOSH}:${EL2Network.GOSH}`]: 0n,
+ },
networks: {
[EL2Network.ETH]: {
label: 'Ethereum',
diff --git a/web/src/v6.1.0/types/l2.types.ts b/web/src/v6.1.0/types/l2.types.ts
index 5b913f247..41310e52c 100644
--- a/web/src/v6.1.0/types/l2.types.ts
+++ b/web/src/v6.1.0/types/l2.types.ts
@@ -26,6 +26,7 @@ export type TL2TransferData = {
instance: TIP3Wallet | null
address: string
}
+ comissions: { [route: string]: bigint }
networks: {
[key: string]: {
label: string