Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
03c9e582
Commit
03c9e582
authored
Feb 14, 2025
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
contract method form
parent
3a9f3d18
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
322 additions
and
311 deletions
+322
-311
globalCss.ts
toolkit/theme/globalCss.ts
+7
-0
field.recipe.ts
toolkit/theme/recipes/field.recipe.ts
+3
-3
input.recipe.ts
toolkit/theme/recipes/input.recipe.ts
+2
-2
ContractAbi.tsx
ui/address/contract/methods/ContractAbi.tsx
+12
-10
ContractAbiItem.tsx
ui/address/contract/methods/ContractAbiItem.tsx
+72
-66
ContractConnectWallet.tsx
ui/address/contract/methods/ContractConnectWallet.tsx
+1
-1
ContractMethodsCustom.tsx
ui/address/contract/methods/ContractMethodsCustom.tsx
+2
-2
ContractMethodsProxy.tsx
ui/address/contract/methods/ContractMethodsProxy.tsx
+2
-2
ContractMethodsRegular.tsx
ui/address/contract/methods/ContractMethodsRegular.tsx
+2
-2
ContractMethodAddressButton.tsx
...ess/contract/methods/form/ContractMethodAddressButton.tsx
+5
-5
ContractMethodArrayButton.tsx
...dress/contract/methods/form/ContractMethodArrayButton.tsx
+15
-7
ContractMethodFieldAccordion.tsx
...ss/contract/methods/form/ContractMethodFieldAccordion.tsx
+25
-29
ContractMethodFieldInput.tsx
...ddress/contract/methods/form/ContractMethodFieldInput.tsx
+65
-57
ContractMethodFieldLabel.tsx
...ddress/contract/methods/form/ContractMethodFieldLabel.tsx
+3
-6
ContractMethodForm.tsx
ui/address/contract/methods/form/ContractMethodForm.tsx
+30
-29
ContractMethodMultiplyButton.tsx
...ss/contract/methods/form/ContractMethodMultiplyButton.tsx
+52
-69
ContractMethodResultPublicClient.tsx
...ontract/methods/form/ContractMethodResultPublicClient.tsx
+5
-5
ContractMethodResultWalletClient.tsx
...ontract/methods/form/ContractMethodResultWalletClient.tsx
+7
-6
ItemPrimitive.tsx
...ontract/methods/form/resultPublicClient/ItemPrimitive.tsx
+5
-5
ItemTuple.tsx
...ss/contract/methods/form/resultPublicClient/ItemTuple.tsx
+2
-2
useScrollToMethod.ts
ui/address/contract/methods/useScrollToMethod.ts
+2
-2
Hint.tsx
ui/shared/Hint.tsx
+3
-1
No files found.
toolkit/theme/globalCss.ts
View file @
03c9e582
...
...
@@ -22,6 +22,13 @@ const globalCss: SystemConfig['globalCss'] = {
form
:
{
w
:
'
100%
'
,
},
input
:
{
// hide number input arrows in Google Chrome
'
&::-webkit-outer-spin-button, &::-webkit-inner-spin-button
'
:
{
WebkitAppearance
:
'
none
'
,
margin
:
0
,
},
},
...
recaptcha
,
...
scrollbar
,
...
addressEntity
,
...
...
toolkit/theme/recipes/field.recipe.ts
View file @
03c9e582
...
...
@@ -12,7 +12,7 @@ export const recipe = defineSlotRecipe({
display
:
'
flex
'
,
width
:
'
100%
'
,
position
:
'
relative
'
,
gap
:
'
1
.5
'
,
gap
:
'
1
'
,
},
label
:
{
display
:
'
flex
'
,
...
...
@@ -36,11 +36,11 @@ export const recipe = defineSlotRecipe({
fontWeight
:
'
medium
'
,
gap
:
'
1
'
,
color
:
'
input.fg.error
'
,
textStyle
:
'
xs
'
,
textStyle
:
'
sm
'
,
},
helperText
:
{
color
:
'
fg.muted
'
,
textStyle
:
'
xs
'
,
textStyle
:
'
sm
'
,
},
},
...
...
toolkit/theme/recipes/input.recipe.ts
View file @
03c9e582
...
...
@@ -6,7 +6,7 @@ export const recipe = defineRecipe({
minWidth
:
'
0
'
,
outline
:
'
0
'
,
position
:
'
relative
'
,
appearance
:
'
none
'
,
appearance
:
'
textfield
'
,
textAlign
:
'
start
'
,
borderRadius
:
'
base
'
,
height
:
'
var(--input-height)
'
,
...
...
@@ -27,7 +27,7 @@ export const recipe = defineRecipe({
variants
:
{
size
:
{
sm
:
{
textStyle
:
'
sm
'
,
textStyle
:
'
md
'
,
px
:
'
2
'
,
'
--input-height
'
:
'
sizes.8
'
,
},
...
...
ui/address/contract/methods/ContractAbi.tsx
View file @
03c9e582
import
{
Accordion
,
Box
,
Flex
,
Link
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Flex
}
from
'
@chakra-ui/react
'
;
import
{
range
}
from
'
es-toolkit
'
;
import
React
from
'
react
'
;
...
...
@@ -7,7 +7,8 @@ import type { SmartContractMethod } from './types';
import
{
route
}
from
'
nextjs-routes
'
;
import
{
apos
}
from
'
lib/html-entities
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
{
AccordionRoot
}
from
'
toolkit/chakra/accordion
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
ContractAbiItem
from
'
./ContractAbiItem
'
;
import
useFormSubmit
from
'
./useFormSubmit
'
;
...
...
@@ -22,15 +23,15 @@ interface Props {
}
const
ContractAbi
=
({
abi
,
addressHash
,
sourceAddress
,
tab
,
visibleItems
}:
Props
)
=>
{
const
[
expandedSections
,
setExpandedSections
]
=
React
.
useState
<
Array
<
number
>>
(
abi
.
length
===
1
?
[
0
]
:
[]);
const
[
expandedSections
,
setExpandedSections
]
=
React
.
useState
<
Array
<
string
>>
(
abi
.
length
===
1
?
[
'
0
'
]
:
[]);
const
[
id
,
setId
]
=
React
.
useState
(
0
);
useScrollToMethod
(
abi
,
setExpandedSections
);
const
handleFormSubmit
=
useFormSubmit
({
addressHash
});
const
handleAccordionStateChange
=
React
.
useCallback
((
newValue
:
Array
<
number
>
)
=>
{
setExpandedSections
(
newV
alue
);
const
handleAccordionStateChange
=
React
.
useCallback
((
{
value
}:
{
value
:
Array
<
string
>
}
)
=>
{
setExpandedSections
(
v
alue
);
},
[]);
const
handleExpandAll
=
React
.
useCallback
(()
=>
{
...
...
@@ -39,7 +40,7 @@ const ContractAbi = ({ abi, addressHash, sourceAddress, tab, visibleItems }: Pro
}
if
(
expandedSections
.
length
<
abi
.
length
)
{
setExpandedSections
(
range
(
0
,
abi
.
length
));
setExpandedSections
(
range
(
0
,
abi
.
length
)
.
map
(
String
)
);
}
else
{
setExpandedSections
([]);
}
...
...
@@ -62,13 +63,14 @@ const ContractAbi = ({ abi, addressHash, sourceAddress, tab, visibleItems }: Pro
)
}
<
Link
onClick=
{
handleReset
}
ml=
{
3
}
>
Reset
</
Link
>
</
Flex
>
<
Accordion
allowMultiple
position=
"relative"
onChange=
{
handleAccordionStateChange
}
index
=
{
expandedSections
}
>
<
Accordion
Root
multiple
lazyMount
position=
"relative"
onValueChange=
{
handleAccordionStateChange
}
value
=
{
expandedSections
}
>
{
abi
.
map
((
item
,
index
)
=>
(
<
ContractAbiItem
key=
{
index
}
id=
{
id
}
index=
{
index
}
data=
{
item
}
isOpen=
{
expandedSections
.
includes
(
String
(
index
))
}
isVisible=
{
!
visibleItems
||
visibleItems
.
includes
(
index
)
}
addressHash=
{
addressHash
}
sourceAddress=
{
sourceAddress
}
...
...
@@ -76,18 +78,18 @@ const ContractAbi = ({ abi, addressHash, sourceAddress, tab, visibleItems }: Pro
onSubmit=
{
handleFormSubmit
}
/>
))
}
</
Accordion
>
</
Accordion
Root
>
{
!
hasVisibleItems
&&
(
<
div
>
<
div
>
Couldn
{
apos
}
t find any method that matches your query.
</
div
>
<
div
>
You can use custom ABI for this contract without verifying the contract in the
{
'
'
}
<
Link
Internal
<
Link
href=
{
route
({
pathname
:
'
/address/[hash]
'
,
query
:
{
hash
:
addressHash
,
tab
:
'
read_write_custom_methods
'
}
})
}
scroll=
{
false
}
>
Custom ABI
</
Link
Internal
>
</
Link
>
{
'
'
}
tab.
</
div
>
</
div
>
...
...
ui/address/contract/methods/ContractAbiItem.tsx
View file @
03c9e582
import
{
AccordionButton
,
AccordionIcon
,
AccordionItem
,
AccordionPanel
,
Alert
,
Box
,
Tag
}
from
'
@chakra-ui/react
'
;
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
Element
}
from
'
react-scroll
'
;
...
...
@@ -7,6 +7,9 @@ import type { FormSubmitHandler, SmartContractMethod } from './types';
import
{
route
}
from
'
nextjs-routes
'
;
import
config
from
'
configs/app
'
;
import
{
AccordionItem
,
AccordionItemContent
,
AccordionItemTrigger
}
from
'
toolkit/chakra/accordion
'
;
import
{
Alert
}
from
'
toolkit/chakra/alert
'
;
import
{
Badge
}
from
'
toolkit/chakra/badge
'
;
import
CopyToClipboard
from
'
ui/shared/CopyToClipboard
'
;
import
Hint
from
'
ui/shared/Hint
'
;
...
...
@@ -23,9 +26,10 @@ interface Props {
tab
:
string
;
onSubmit
:
FormSubmitHandler
;
isVisible
?:
boolean
;
isOpen
:
boolean
;
}
const
ContractAbiItem
=
({
data
,
index
,
id
,
addressHash
,
sourceAddress
,
tab
,
onSubmit
,
isVisible
=
true
}:
Props
)
=>
{
const
ContractAbiItem
=
({
data
,
index
,
id
,
addressHash
,
sourceAddress
,
tab
,
onSubmit
,
isVisible
=
true
,
isOpen
}:
Props
)
=>
{
const
[
attempt
,
setAttempt
]
=
React
.
useState
(
0
);
const
url
=
React
.
useMemo
(()
=>
{
...
...
@@ -47,74 +51,76 @@ const ContractAbiItem = ({ data, index, id, addressHash, sourceAddress, tab, onS
const
isRead
=
isReadMethod
(
data
);
return
(
<
AccordionItem
as=
"section"
_first=
{
{
borderTopWidth
:
0
}
}
_last=
{
{
borderBottomWidth
:
0
}
}
display=
{
isVisible
?
'
block
'
:
'
none
'
}
>
{
({
isExpanded
})
=>
(
<>
<
Element
as=
"h2"
name=
{
getElementName
(
data
)
}
>
<
AccordionButton
px=
{
0
}
py=
{
3
}
_hover=
{
{
bgColor
:
'
inherit
'
}
}
wordBreak=
"break-all"
textAlign=
"left"
as=
"div"
cursor=
"pointer"
display=
"flex"
alignItems=
"center"
columnGap=
{
2
}
>
<
CopyToClipboard
text=
{
url
}
type=
"link"
ml=
{
0
}
color=
"text_secondary"
/>
<
Box
as=
"div"
fontWeight=
{
500
}
display=
"flex"
alignItems=
"center"
>
{
index
+
1
}
.
{
data
.
type
===
'
fallback
'
||
data
.
type
===
'
receive
'
?
data
.
type
:
data
.
name
}
{
data
.
type
===
'
fallback
'
&&
(
<
Hint
label=
{
`The fallback function is executed on a call to the contract if none of the other functions match
the given function signature, or if no data was supplied at all and there is no receive Ether function.
<
AccordionItem
as=
"section"
value=
{
String
(
index
)
}
_first=
{
{
borderTopWidth
:
0
}
}
_last=
{
{
borderBottomWidth
:
0
}
}
display=
{
isVisible
?
'
block
'
:
'
none
'
}
>
<
Element
as=
"h2"
name=
{
getElementName
(
data
)
}
>
<
AccordionItemTrigger
px=
{
0
}
py=
{
3
}
_hover=
{
{
bgColor
:
'
inherit
'
}
}
wordBreak=
"break-all"
textAlign=
"left"
cursor=
"pointer"
display=
"flex"
alignItems=
"center"
columnGap=
{
2
}
>
<
CopyToClipboard
text=
{
url
}
type=
"link"
ml=
{
0
}
color=
"text_secondary"
as=
"div"
/>
<
Box
fontWeight=
{
500
}
display=
"flex"
alignItems=
"center"
>
{
index
+
1
}
.
{
data
.
type
===
'
fallback
'
||
data
.
type
===
'
receive
'
?
data
.
type
:
data
.
name
}
{
data
.
type
===
'
fallback
'
&&
(
<
Hint
label=
{
`The fallback function is executed on a call to the contract if none of the other functions match
the given function signature, or if no data was supplied at all and there is no receive Ether function.
The fallback function always receives data, but in order to also receive Ether it must be marked payable.`
}
ml=
{
1
}
/>
)
}
{
data
.
type
===
'
receive
'
&&
(
<
Hint
label=
{
`The receive function is executed on a call to the contract with empty calldata.
This is the function that is executed on plain Ether transfers (e.g. via .send() or .transfer()).
If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer.
If neither a receive Ether nor a payable fallback function is present,
}
ml=
{
1
}
as=
"div"
/>
)
}
{
data
.
type
===
'
receive
'
&&
(
<
Hint
label=
{
`The receive function is executed on a call to the contract with empty calldata.
This is the function that is executed on plain Ether transfers (e.g. via .send() or .transfer()).
If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer.
If neither a receive Ether nor a payable fallback function is present,
the contract cannot receive Ether through regular transactions and throws an exception.`
}
ml=
{
1
}
/>
)
}
</
Box
>
<
Tag
colorScheme=
{
isRead
?
'
black-purple
'
:
'
black-blue
'
}
flexShrink=
{
0
}
>
{
isRead
?
'
read
'
:
'
write
'
}
</
Tag
>
{
'
method_id
'
in
data
&&
(
<
Tag
display=
"inline-flex"
alignItems=
"center"
flexShrink=
{
0
}
>
{
data
.
method_id
}
<
CopyToClipboard
text=
{
data
.
method_id
}
/>
</
Tag
>
)
}
<
AccordionIcon
transform=
{
isExpanded
?
'
rotate(0deg)
'
:
'
rotate(-90deg)
'
}
color=
"gray.500"
/>
</
AccordionButton
>
</
Element
>
<
AccordionPanel
pb=
{
4
}
pr=
{
0
}
pl=
"28px"
w=
"calc(100% - 6px)"
>
{
'
is_invalid
'
in
data
&&
data
.
is_invalid
?
(
<
Alert
status=
"warning"
>
An error occurred while parsing the method signature.
</
Alert
>
)
:
(
<
ContractMethodForm
key=
{
id
+
'
_
'
+
index
+
'
_
'
+
attempt
}
data=
{
data
}
attempt=
{
attempt
}
onSubmit=
{
onSubmit
}
onReset=
{
handleReset
}
isOpen=
{
isExpanded
}
}
ml=
{
1
}
as=
"div"
/>
)
}
</
AccordionPanel
>
</>
)
}
</
Box
>
<
Badge
colorPalette=
{
isRead
?
'
purple_alt
'
:
'
blue_alt
'
}
flexShrink=
{
0
}
>
{
isRead
?
'
read
'
:
'
write
'
}
</
Badge
>
{
'
method_id
'
in
data
&&
(
<
Badge
display=
"inline-flex"
alignItems=
"center"
flexShrink=
{
0
}
>
{
data
.
method_id
}
<
CopyToClipboard
text=
{
data
.
method_id
}
as=
"div"
/>
</
Badge
>
)
}
</
AccordionItemTrigger
>
</
Element
>
<
AccordionItemContent
pb=
{
4
}
pr=
{
0
}
pl=
"28px"
w=
"calc(100% - 6px)"
>
{
'
is_invalid
'
in
data
&&
data
.
is_invalid
?
(
<
Alert
status=
"warning"
>
An error occurred while parsing the method signature.
</
Alert
>
)
:
(
<
ContractMethodForm
key=
{
id
+
'
_
'
+
index
+
'
_
'
+
attempt
}
data=
{
data
}
attempt=
{
attempt
}
onSubmit=
{
onSubmit
}
onReset=
{
handleReset
}
isOpen=
{
isOpen
}
/>
)
}
</
AccordionItemContent
>
</
AccordionItem
>
);
};
...
...
ui/address/contract/methods/ContractConnectWallet.tsx
View file @
03c9e582
...
...
@@ -55,7 +55,7 @@ const ContractConnectWallet = ({ isLoading }: Props) => {
return
(
<
Skeleton
loading=
{
isLoading
}
>
<
Alert
status=
{
web3Wallet
.
address
?
'
success
'
:
'
warning
'
}
>
<
Alert
status=
{
web3Wallet
.
address
?
'
success
'
:
'
warning
'
}
descriptionProps=
{
{
alignItems
:
'
center
'
}
}
>
{
content
}
</
Alert
>
</
Skeleton
>
...
...
ui/address/contract/methods/ContractMethodsCustom.tsx
View file @
03c9e582
...
...
@@ -93,9 +93,9 @@ const ContractMethodsCustom = ({ isLoading: isLoadingProp }: Props) => {
onChange=
{
filters
.
onChange
}
isLoading=
{
isLoading
}
/>
{
/*
<ContractMethodsContainer isLoading={ isLoading } isEmpty={ abi.length === 0 } type={ filters.methodType }>
<
ContractMethodsContainer
isLoading=
{
isLoading
}
isEmpty=
{
abi
.
length
===
0
}
type=
{
filters
.
methodType
}
>
<
ContractAbi
abi=
{
abi
}
tab=
{
tab
}
addressHash=
{
addressHash
}
visibleItems=
{
filters
.
visibleItems
}
/>
</ContractMethodsContainer>
*/
}
</
ContractMethodsContainer
>
</>
)
:
(
<>
...
...
ui/address/contract/methods/ContractMethodsProxy.tsx
View file @
03c9e582
...
...
@@ -58,7 +58,7 @@ const ContractMethodsProxy = ({ implementations, isLoading: isInitialLoading }:
isLoading=
{
isInitialLoading
}
/>
</
div
>
{
/*
<ContractMethodsContainer
<
ContractMethodsContainer
key=
{
selectedItem
.
address
}
isLoading=
{
isInitialLoading
||
contractQuery
.
isPending
}
isEmpty=
{
abi
.
length
===
0
}
...
...
@@ -72,7 +72,7 @@ const ContractMethodsProxy = ({ implementations, isLoading: isInitialLoading }:
visibleItems=
{
filters
.
visibleItems
}
sourceAddress=
{
selectedItem
.
address
}
/>
</ContractMethodsContainer>
*/
}
</
ContractMethodsContainer
>
</
Flex
>
);
};
...
...
ui/address/contract/methods/ContractMethodsRegular.tsx
View file @
03c9e582
...
...
@@ -36,9 +36,9 @@ const ContractMethodsRegular = ({ abi, isLoading }: Props) => {
onChange=
{
filters
.
onChange
}
isLoading=
{
isLoading
}
/>
{
/*
<ContractMethodsContainer isLoading={ isLoading } isEmpty={ formattedAbi.length === 0 } type={ filters.methodType }>
<
ContractMethodsContainer
isLoading=
{
isLoading
}
isEmpty=
{
formattedAbi
.
length
===
0
}
type=
{
filters
.
methodType
}
>
<
ContractAbi
abi=
{
formattedAbi
}
tab=
{
tab
}
addressHash=
{
addressHash
}
visibleItems=
{
filters
.
visibleItems
}
/>
</ContractMethodsContainer>
*/
}
</
ContractMethodsContainer
>
</
Flex
>
);
};
...
...
ui/address/contract/methods/form/ContractMethodAddressButton.tsx
View file @
03c9e582
import
{
Button
,
Tooltip
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
useAccount
from
'
lib/web3/useAccount
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
Tooltip
}
from
'
toolkit/chakra/tooltip
'
;
interface
Props
{
onClick
:
(
address
:
string
)
=>
void
;
...
...
@@ -16,16 +17,15 @@ const ContractMethodAddressButton = ({ onClick, isDisabled }: Props) => {
},
[
address
,
onClick
]);
return
(
<
Tooltip
label
=
{
!
address
?
'
Connect your wallet to enter your address.
'
:
undefined
}
>
<
Tooltip
content
=
{
!
address
?
'
Connect your wallet to enter your address.
'
:
undefined
}
>
<
Button
variant=
"subtle"
colorScheme=
"gray"
size=
"xs"
fontSize=
"normal
"
textStyle=
"md
"
fontWeight=
{
500
}
ml=
{
1
}
onClick=
{
handleClick
}
isD
isabled=
{
isDisabled
||
!
address
}
d
isabled=
{
isDisabled
||
!
address
}
>
Self
</
Button
>
...
...
ui/address/contract/methods/form/ContractMethodArrayButton.tsx
View file @
03c9e582
import
{
IconButton
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
IconButton
}
from
'
toolkit/chakra/icon-button
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
interface
Props
{
...
...
@@ -12,19 +13,26 @@ interface Props {
}
const
ContractMethodArrayButton
=
({
className
,
type
,
index
,
onClick
,
isDisabled
}:
Props
)
=>
{
const
handleClick
=
React
.
useCallback
((
event
:
React
.
MouseEvent
<
HTMLButtonElement
>
)
=>
{
event
.
stopPropagation
();
onClick
(
event
);
},
[
onClick
]);
return
(
<
IconButton
as=
"div"
className=
{
className
}
aria
-
label=
{
type
}
data
-
index=
{
index
}
variant=
"outline"
w=
"20px"
h=
"20px"
boxSize=
{
5
}
flexShrink=
{
0
}
onClick=
{
onClick
}
icon=
{
<
IconSvg
name=
{
type
===
'
remove
'
?
'
minus
'
:
'
plus
'
}
boxSize=
{
3
}
/>
}
isDisabled=
{
isDisabled
}
/>
onClick=
{
handleClick
}
disabled=
{
isDisabled
}
>
<
IconSvg
name=
{
type
===
'
remove
'
?
'
minus
'
:
'
plus
'
}
boxSize=
{
3
}
/>
</
IconButton
>
);
};
...
...
ui/address/contract/methods/form/ContractMethodFieldAccordion.tsx
View file @
03c9e582
import
{
Accordion
,
AccordionButton
,
AccordionIcon
,
AccordionItem
,
AccordionPanel
,
Box
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
AccordionItem
,
AccordionItemContent
,
AccordionItemTrigger
,
AccordionRoot
}
from
'
toolkit/chakra/accordion
'
;
import
ContractMethodArrayButton
from
'
./ContractMethodArrayButton
'
;
export
interface
Props
{
...
...
@@ -14,37 +16,31 @@ export interface Props {
}
const
ContractMethodFieldAccordion
=
({
label
,
level
,
children
,
onAddClick
,
onRemoveClick
,
index
,
isInvalid
}:
Props
)
=>
{
const
bgColorLevel0
=
useColorModeValue
(
'
blackAlpha.50
'
,
'
whiteAlpha.50
'
)
;
const
bgColor
=
useColorModeValue
(
'
whiteAlpha.700
'
,
'
blackAlpha.700
'
)
;
const
bgColorLevel0
=
{
_light
:
'
blackAlpha.50
'
,
_dark
:
'
whiteAlpha.50
'
}
;
const
bgColor
=
{
_light
:
'
whiteAlpha.700
'
,
_dark
:
'
blackAlpha.700
'
}
;
return
(
<
Accordion
allowToggle
w=
"100%"
bgColor=
{
level
===
0
?
bgColorLevel0
:
bgColor
}
borderRadius=
"base"
>
<
AccordionItem
_first=
{
{
borderTopWidth
:
0
}
}
_last=
{
{
borderBottomWidth
:
0
}
}
>
{
({
isExpanded
})
=>
(
<>
<
AccordionButton
as=
"div"
cursor=
"pointer"
px=
"6px"
py=
"6px"
wordBreak=
"break-all"
textAlign=
"left"
_hover=
{
{
bgColor
:
'
inherit
'
}
}
>
<
AccordionIcon
transform=
{
isExpanded
?
'
rotate(0deg)
'
:
'
rotate(-90deg)
'
}
color=
"gray.500"
/>
<
Box
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
700
}
mr=
"auto"
ml=
{
1
}
color=
{
isInvalid
?
'
error
'
:
undefined
}
>
{
label
}
</
Box
>
{
onRemoveClick
&&
<
ContractMethodArrayButton
index=
{
index
}
onClick=
{
onRemoveClick
}
type=
"remove"
/>
}
{
onAddClick
&&
<
ContractMethodArrayButton
index=
{
index
}
onClick=
{
onAddClick
}
type=
"add"
ml=
{
2
}
/>
}
</
AccordionButton
>
<
AccordionPanel
display=
"flex"
flexDir=
"column"
rowGap=
{
1
}
pl=
"18px"
pr=
"6px"
>
{
children
}
</
AccordionPanel
>
</>
)
}
<
AccordionRoot
w=
"100%"
bgColor=
{
level
===
0
?
bgColorLevel0
:
bgColor
}
borderRadius=
"base"
lazyMount
>
<
AccordionItem
value=
"default"
_first=
{
{
borderTopWidth
:
0
}
}
_last=
{
{
borderBottomWidth
:
0
}
}
>
<
AccordionItemTrigger
indicatorPlacement=
"start"
px=
"6px"
py=
"6px"
wordBreak=
"break-all"
textAlign=
"left"
_hover=
{
{
bgColor
:
'
inherit
'
}
}
>
<
Box
textStyle=
"sm"
fontWeight=
{
700
}
mr=
"auto"
color=
{
isInvalid
?
'
error
'
:
undefined
}
>
{
label
}
</
Box
>
{
onRemoveClick
&&
index
!==
undefined
&&
<
ContractMethodArrayButton
index=
{
index
}
onClick=
{
onRemoveClick
}
type=
"remove"
/>
}
{
onAddClick
&&
index
!==
undefined
&&
<
ContractMethodArrayButton
index=
{
index
}
onClick=
{
onAddClick
}
type=
"add"
ml=
{
2
}
/>
}
</
AccordionItemTrigger
>
<
AccordionItemContent
display=
"flex"
flexDir=
"column"
rowGap=
{
1
}
pl=
"18px"
pr=
"6px"
>
{
children
}
</
AccordionItemContent
>
</
AccordionItem
>
</
Accordion
>
</
Accordion
Root
>
);
};
...
...
ui/address/contract/methods/form/ContractMethodFieldInput.tsx
View file @
03c9e582
import
{
Box
,
Button
,
Flex
,
FormControl
,
Input
,
InputGroup
,
InputRightElement
,
chakra
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
useController
,
useFormContext
}
from
'
react-hook-form
'
;
import
{
NumericFormat
}
from
'
react-number-format
'
;
//
import { NumericFormat } from 'react-number-format';
import
type
{
ContractAbiItemInput
}
from
'
../types
'
;
import
{
HOUR
,
SECOND
}
from
'
lib/consts
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
Field
}
from
'
toolkit/chakra/field
'
;
import
{
Input
}
from
'
toolkit/chakra/input
'
;
import
{
InputGroup
}
from
'
toolkit/chakra/input-group
'
;
import
ClearButton
from
'
ui/shared/ClearButton
'
;
import
ContractMethodAddressButton
from
'
./ContractMethodAddressButton
'
;
...
...
@@ -43,8 +47,8 @@ const ContractMethodFieldInput = ({ data, hideLabel, path: name, className, isDi
const
{
control
,
setValue
,
getValues
}
=
useFormContext
();
const
{
field
,
fieldState
}
=
useController
({
control
,
name
,
rules
:
{
validate
}
});
const
inputBgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
)
;
const
nativeCoinRowBgColor
=
useColorModeValue
(
'
gray.100
'
,
'
gray.700
'
)
;
const
inputBgColor
=
{
_light
:
'
white
'
,
_dark
:
'
black
'
}
;
const
nativeCoinRowBgColor
=
{
_light
:
'
gray.100
'
,
_dark
:
'
gray.700
'
}
;
const
hasMultiplyButton
=
argTypeMatchInt
&&
Number
(
argTypeMatchInt
.
power
)
>=
64
;
...
...
@@ -125,6 +129,46 @@ const ContractMethodFieldInput = ({ data, hideLabel, path: name, className, isDi
const
error
=
fieldState
.
error
;
const
inputEndElement
=
(
<
Flex
alignItems=
"center"
>
{
field
.
value
!==
undefined
&&
field
.
value
!==
''
&&
<
ClearButton
onClick=
{
handleClear
}
isDisabled=
{
isDisabled
}
boxSize=
{
6
}
/>
}
{
data
.
type
===
'
address
'
&&
<
ContractMethodAddressButton
onClick=
{
handleAddressButtonClick
}
isDisabled=
{
isDisabled
}
/>
}
{
argTypeMatchInt
&&
!
isNativeCoin
&&
(
hasTimestampButton
?
(
<
Button
variant=
"subtle"
size=
"xs"
textStyle=
"md"
fontWeight=
{
500
}
ml=
{
1
}
onClick=
{
handleTimestampButtonClick
}
disabled=
{
isDisabled
}
>
Now+1h
</
Button
>
)
:
(
<
Button
variant=
"subtle"
size=
"xs"
textStyle=
"md"
fontWeight=
{
500
}
ml=
{
1
}
onClick=
{
handleMaxIntButtonClick
}
disabled=
{
isDisabled
}
>
Max
</
Button
>
))
}
{
hasMultiplyButton
&&
(
<
ContractMethodMultiplyButton
onClick=
{
handleMultiplyButtonClick
}
isDisabled=
{
isDisabled
}
initialValue=
{
intPower
}
onChange=
{
setIntPower
}
/>
)
}
</
Flex
>
);
return
(
<
Flex
className=
{
className
}
...
...
@@ -138,73 +182,37 @@ const ContractMethodFieldInput = ({ data, hideLabel, path: name, className, isDi
py=
{
isNativeCoin
?
1
:
0
}
>
{
!
hideLabel
&&
<
ContractMethodFieldLabel
data=
{
data
}
isOptional=
{
isOptional
}
level=
{
level
}
/>
}
<
FormControl
isDisabled=
{
isDisabled
}
>
<
InputGroup
size=
"xs"
>
<
Field
invalid=
{
Boolean
(
error
)
}
errorText=
{
error
?.
message
}
disabled=
{
isDisabled
}
>
<
InputGroup
endElement=
{
inputEndElement
}
endElementProps=
{
{
pl
:
0
,
pr
:
1
}
}
>
<
Input
{
...
field
}
{
...
(
argTypeMatchInt
?
{
as
:
NumericFormat
,
thousandSeparator
:
'
',
decimalScale
:
0,
allowNegative
:
!
argTypeMatchInt
.
isUnsigned
,
getInputRef
:
(
element
:
HTMLInputElement
)
=
>
{
ref
.
current
=
element
;
}
,
} :
{}
) }
// TODO @tom2drum fix formatting of numeric input
// { ...(argTypeMatchInt ? {
// as: NumericFormat,
// thousandSeparator: ' ',
// decimalScale: 0,
// allowNegative: !argTypeMatchInt.isUnsigned,
// getInputRef: (element: HTMLInputElement) => {
// ref.current = element;
// },
// } : {}) }
// as we use mutable ref, we have to cast it to React.LegacyRef<HTMLInputElement> to trick chakra and typescript
ref=
{
ref
as
React
.
LegacyRef
<
HTMLInputElement
>
|
undefined
}
size=
"sm"
onChange=
{
handleChange
}
onPaste=
{
handlePaste
}
required=
{
!
isOptional
}
isInvalid=
{
Boolean
(
error
)
}
placeholder=
{
data
.
type
}
autoComplete=
"off"
data
-1
p
-
ignore
bgColor=
{
inputBgColor
}
paddingRight=
{
hasMultiplyButton
?
'
120px
'
:
'
40px
'
}
/>
<
InputRightElement
w=
"auto"
right=
{
1
}
bgColor=
{
inputBgColor
}
h=
"calc(100% - 4px)"
top=
"2px"
borderRadius=
"base"
>
{
field
.
value
!==
undefined
&&
field
.
value
!==
''
&&
<
ClearButton
onClick=
{
handleClear
}
isDisabled=
{
isDisabled
}
/>
}
{
data
.
type
===
'
address
'
&&
<
ContractMethodAddressButton
onClick=
{
handleAddressButtonClick
}
isDisabled=
{
isDisabled
}
/>
}
{
argTypeMatchInt
&&
!
isNativeCoin
&&
(
hasTimestampButton
?
(
<
Button
variant=
"subtle"
colorScheme=
"gray"
size=
"xs"
fontSize=
"normal"
fontWeight=
{
500
}
ml=
{
1
}
onClick=
{
handleTimestampButtonClick
}
isDisabled=
{
isDisabled
}
>
Now+1h
</
Button
>
)
:
(
<
Button
variant=
"subtle"
colorScheme=
"gray"
size=
"xs"
fontSize=
"normal"
fontWeight=
{
500
}
ml=
{
1
}
onClick=
{
handleMaxIntButtonClick
}
isDisabled=
{
isDisabled
}
>
Max
</
Button
>
))
}
{
hasMultiplyButton
&&
(
<
ContractMethodMultiplyButton
onClick=
{
handleMultiplyButtonClick
}
isDisabled=
{
isDisabled
}
initialValue=
{
intPower
}
onChange=
{
setIntPower
}
/>
)
}
</
InputRightElement
>
</
InputGroup
>
{
error
&&
<
Box
color=
"error"
fontSize=
"sm"
lineHeight=
{
5
}
mt=
{
1
}
>
{
error
.
message
}
</
Box
>
}
</
FormControl
>
</
Field
>
</
Flex
>
);
};
...
...
ui/address/contract/methods/form/ContractMethodFieldLabel.tsx
View file @
03c9e582
import
{
Box
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
ContractAbiItemInput
}
from
'
../types
'
;
...
...
@@ -12,17 +12,14 @@ interface Props {
}
const
ContractMethodFieldLabel
=
({
data
,
isOptional
,
level
}:
Props
)
=>
{
const
color
=
useColorModeValue
(
'
blackAlpha.600
'
,
'
whiteAlpha.600
'
);
return
(
<
Box
w=
"250px"
fontSize=
"sm"
lineHeight=
{
5
}
textStyle=
"sm"
py=
"6px"
flexShrink=
{
0
}
fontWeight=
{
500
}
color=
{
level
>
1
?
color
:
undefined
}
color=
{
level
>
1
?
{
_light
:
'
blackAlpha.600
'
,
_dark
:
'
whiteAlpha.600
'
}
:
undefined
}
>
{
getFieldLabel
(
data
,
!
isOptional
)
}
</
Box
>
...
...
ui/address/contract/methods/form/ContractMethodForm.tsx
View file @
03c9e582
import
{
Box
,
Button
,
Flex
,
Tooltip
,
chakra
,
useDisclosure
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Flex
,
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
SubmitHandler
}
from
'
react-hook-form
'
;
import
{
useForm
,
FormProvider
}
from
'
react-hook-form
'
;
...
...
@@ -9,6 +9,9 @@ import type { FormSubmitHandler, FormSubmitResult, MethodCallStrategy, SmartCont
import
config
from
'
configs/app
'
;
import
{
SECOND
}
from
'
lib/consts
'
;
import
*
as
mixpanel
from
'
lib/mixpanel/index
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
Tooltip
}
from
'
toolkit/chakra/tooltip
'
;
import
{
useDisclosure
}
from
'
toolkit/hooks/useDisclosure
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
isReadMethod
}
from
'
../utils
'
;
...
...
@@ -139,10 +142,10 @@ const ContractMethodForm = ({ data, attempt, onSubmit, onReset, isOpen }: Props)
const
buttonCallStrategy
=
methodType
===
'
write
'
?
'
write
'
:
'
read
'
;
return
(
<
Tooltip
label=
{
isDisabled
?
NO_WALLET_CLIENT_TEXT
:
undefined
}
maxW=
"300px"
>
<
Tooltip
content=
{
NO_WALLET_CLIENT_TEXT
}
disabled=
{
!
isDisabled
}
>
<
Button
isL
oading=
{
callStrategy
===
buttonCallStrategy
&&
isLoading
}
isD
isabled=
{
isLoading
||
isDisabled
}
l
oading=
{
callStrategy
===
buttonCallStrategy
&&
isLoading
}
d
isabled=
{
isLoading
||
isDisabled
}
onClick=
{
handleButtonClick
}
loadingText=
{
text
}
variant=
"outline"
...
...
@@ -174,8 +177,8 @@ const ContractMethodForm = ({ data, attempt, onSubmit, onReset, isOpen }: Props)
return
(
<
Button
isL
oading=
{
callStrategy
===
buttonCallStrategy
&&
isLoading
}
isD
isabled=
{
isLoading
}
l
oading=
{
callStrategy
===
buttonCallStrategy
&&
isLoading
}
d
isabled=
{
isLoading
}
onClick=
{
handleButtonClick
}
loadingText=
{
text
}
variant=
"outline"
...
...
@@ -183,7 +186,6 @@ const ContractMethodForm = ({ data, attempt, onSubmit, onReset, isOpen }: Props)
flexShrink=
{
0
}
width=
"min-content"
px=
{
4
}
mr=
{
3
}
type=
"submit"
data
-
call
-
strategy=
{
buttonCallStrategy
}
>
...
...
@@ -210,15 +212,14 @@ const ContractMethodForm = ({ data, attempt, onSubmit, onReset, isOpen }: Props)
return
(
<
Tooltip
isD
isabled=
{
isDisabled
}
label
=
"Copied"
d
isabled=
{
isDisabled
}
content
=
"Copied"
closeDelay=
{
SECOND
}
isOpen=
{
calldataButtonTooltip
.
isOpen
}
onClose=
{
calldataButtonTooltip
.
onClose
}
open=
{
calldataButtonTooltip
.
open
}
>
<
Button
isL
oading=
{
callStrategy
===
buttonCallStrategy
&&
isLoading
}
isD
isabled=
{
isDisabled
}
l
oading=
{
callStrategy
===
buttonCallStrategy
&&
isLoading
}
d
isabled=
{
isDisabled
}
onClick=
{
handleButtonClick
}
loadingText=
{
text
}
variant=
"outline"
...
...
@@ -226,7 +227,6 @@ const ContractMethodForm = ({ data, attempt, onSubmit, onReset, isOpen }: Props)
flexShrink=
{
0
}
width=
"min-content"
px=
{
4
}
ml=
{
3
}
type=
"submit"
data
-
call
-
strategy=
{
buttonCallStrategy
}
>
...
...
@@ -282,21 +282,22 @@ const ContractMethodForm = ({ data, attempt, onSubmit, onReset, isOpen }: Props)
return
<
ContractMethodFieldInput
key=
{
index
}
{
...
props
}
path=
{
`${ index }`
}
/>;
})
}
</
Flex
>
{
secondaryButton
}
{
primaryButton
}
{
copyCallDataButton
}
{
result
&&
!
isLoading
&&
(
<
Button
variant=
"simple"
colorScheme=
"blue"
size=
"sm"
onClick=
{
onReset
}
ml=
{
1
}
>
<
IconSvg
name=
"repeat"
boxSize=
{
5
}
mr=
{
1
}
/>
Reset
</
Button
>
)
}
<
Flex
flexDir=
"row"
gap=
{
3
}
>
{
secondaryButton
}
{
primaryButton
}
{
copyCallDataButton
}
{
result
&&
!
isLoading
&&
(
<
Button
variant=
"link"
size=
"sm"
onClick=
{
onReset
}
gap=
{
1
}
>
<
IconSvg
name=
"repeat"
boxSize=
{
5
}
/>
Reset
</
Button
>
)
}
</
Flex
>
</
chakra
.
form
>
</
FormProvider
>
{
result
&&
result
.
source
===
'
wallet_client
'
&&
(
...
...
ui/address/contract/methods/form/ContractMethodMultiplyButton.tsx
View file @
03c9e582
import
{
chakra
,
PopoverBody
,
PopoverContent
,
PopoverTrigger
,
Portal
,
Button
,
List
,
ListItem
,
useDisclosure
,
Input
,
useColorModeValue
,
}
from
'
@chakra-ui/react
'
;
import
{
chakra
,
List
,
Input
,
ListItem
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
times
}
from
'
lib/html-entities
'
;
import
Popover
from
'
ui/shared/chakra/Popover
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
IconButton
}
from
'
toolkit/chakra/icon-button
'
;
import
{
PopoverBody
,
PopoverContent
,
PopoverRoot
,
PopoverTrigger
}
from
'
toolkit/chakra/popover
'
;
import
{
useDisclosure
}
from
'
toolkit/hooks/useDisclosure
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
interface
Props
{
...
...
@@ -27,19 +18,17 @@ interface Props {
const
ContractMethodMultiplyButton
=
({
onClick
,
isDisabled
,
initialValue
,
onChange
}:
Props
)
=>
{
const
[
selectedOption
,
setSelectedOption
]
=
React
.
useState
<
number
|
undefined
>
(
initialValue
);
const
[
customValue
,
setCustomValue
]
=
React
.
useState
<
number
>
();
const
{
isOpen
,
onToggle
,
onClose
}
=
useDisclosure
();
const
dividerColor
=
useColorModeValue
(
'
blackAlpha.200
'
,
'
whiteAlpha.200
'
);
const
{
open
,
onOpenChange
}
=
useDisclosure
();
const
handleOptionClick
=
React
.
useCallback
((
event
:
React
.
MouseEvent
)
=>
{
const
id
=
Number
((
event
.
currentTarget
as
HTMLDivElement
).
getAttribute
(
'
data-id
'
));
if
(
!
Object
.
is
(
id
,
NaN
))
{
setSelectedOption
((
prev
)
=>
prev
===
id
?
undefined
:
id
);
setCustomValue
(
undefined
);
on
Close
(
);
on
OpenChange
({
open
:
false
}
);
onChange
(
id
);
}
},
[
on
Clos
e
,
onChange
]);
},
[
on
OpenChang
e
,
onChange
]);
const
handleInputChange
=
React
.
useCallback
((
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
value
=
Number
(
event
.
target
.
value
);
...
...
@@ -59,90 +48,84 @@ const ContractMethodMultiplyButton = ({ onClick, isDisabled, initialValue, onCha
{
Boolean
(
value
)
&&
(
<
Button
px=
{
1
}
lineHeight=
{
6
}
h=
{
6
}
textStyle=
"md"
size=
"xs"
fontWeight=
{
500
}
ml=
{
1
}
variant=
"subtle"
colorScheme=
"gray"
display=
"inline"
onClick=
{
handleButtonClick
}
isD
isabled=
{
isDisabled
}
d
isabled=
{
isDisabled
}
borderBottomRightRadius=
{
0
}
borderTopRightRadius=
{
0
}
>
{
times
}
<
chakra
.
span
>
10
</
chakra
.
span
>
<
chakra
.
span
fontSize=
"xs"
lineHeight=
{
4
}
verticalAlign=
"super"
>
{
value
}
</
chakra
.
span
>
<
chakra
.
span
fontSize=
"xs"
lineHeight=
"16px"
verticalAlign=
"super"
>
{
value
}
</
chakra
.
span
>
</
Button
>
)
}
<
Popover
placement=
"bottom-end"
isLazy
isOpen=
{
isOpen
}
onClose=
{
onClose
}
>
<
Popover
Root
open=
{
open
}
onOpenChange=
{
onOpenChange
}
positioning=
{
{
placement
:
'
bottom-end
'
}
}
>
<
PopoverTrigger
>
<
Button
<
Icon
Button
variant=
"subtle"
colorScheme=
"gray"
size=
"xs"
cursor=
"pointer"
p=
{
0
}
onClick=
{
onToggle
}
isActive=
{
isOpen
}
isDisabled=
{
isDisabled
}
disabled=
{
isDisabled
}
borderBottomLeftRadius=
{
0
}
borderTopLeftRadius=
{
0
}
borderLeftWidth=
"1px"
borderLeftColor=
{
dividerColor
}
borderLeftColor=
"border.divider"
>
<
IconSvg
name=
"arrows/east-mini"
transitionDuration=
"fast"
transitionProperty=
"transform"
transitionTimingFunction=
"ease-in-out"
transform=
{
isO
pen
?
'
rotate(90deg)
'
:
'
rotate(-90deg)
'
}
transform=
{
o
pen
?
'
rotate(90deg)
'
:
'
rotate(-90deg)
'
}
boxSize=
{
6
}
/>
</
Button
>
</
Icon
Button
>
</
PopoverTrigger
>
<
Portal
>
<
PopoverContent
w=
"110px"
>
<
PopoverBody
py=
{
2
}
>
<
List
>
{
[
8
,
12
,
16
,
18
,
20
].
map
((
id
)
=>
(
<
ListItem
key=
{
id
}
py=
{
2
}
data
-
id=
{
id
}
onClick=
{
handleOptionClick
}
display=
"flex"
justifyContent=
"space-between"
alignItems=
"center"
cursor=
"pointer"
>
<
span
>
10*
{
id
}
</
span
>
{
selectedOption
===
id
&&
<
IconSvg
name=
"check"
boxSize=
{
6
}
color=
"blue.600"
/>
}
</
ListItem
>
))
}
<
ListItem
<
PopoverContent
w=
"110px"
>
<
PopoverBody
textStyle=
"md"
py=
{
2
}
>
<
List
.
Root
>
{
[
8
,
12
,
16
,
18
,
20
].
map
((
id
)
=>
(
<
List
.
Item
key=
{
id
}
py=
{
2
}
data
-
id=
{
id
}
onClick=
{
handleOptionClick
}
display=
"flex"
justifyContent=
"space-between"
alignItems=
"center"
cursor=
"pointer"
>
<
span
>
10*
</
span
>
<
Input
type=
"number"
min=
{
0
}
max=
{
100
}
ml=
{
3
}
size=
"xs"
onChange=
{
handleInputChange
}
value=
{
customValue
||
''
}
/>
</
ListItem
>
</
List
>
</
PopoverBody
>
</
PopoverContent
>
</
Portal
>
</
Popover
>
<
span
>
10*
{
id
}
</
span
>
{
selectedOption
===
id
&&
<
IconSvg
name=
"check"
boxSize=
{
6
}
color=
"blue.600"
/>
}
</
List
.
Item
>
))
}
<
ListItem
py=
{
2
}
display=
"flex"
justifyContent=
"space-between"
alignItems=
"center"
>
<
span
>
10*
</
span
>
<
Input
type=
"number"
min=
{
0
}
max=
{
100
}
ml=
{
3
}
size=
"sm"
onChange=
{
handleInputChange
}
value=
{
customValue
||
''
}
/>
</
ListItem
>
</
List
.
Root
>
</
PopoverBody
>
</
PopoverContent
>
</
PopoverRoot
>
</>
);
};
...
...
ui/address/contract/methods/form/ContractMethodResultPublicClient.tsx
View file @
03c9e582
import
{
Alert
,
Flex
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
Flex
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
AbiFunction
}
from
'
viem
'
;
import
type
{
FormSubmitResultPublicClient
,
ResultViewMode
}
from
'
../types
'
;
import
{
Alert
}
from
'
toolkit/chakra/alert
'
;
import
ResultItem
from
'
./resultPublicClient/Item
'
;
export
interface
Props
{
...
...
@@ -14,8 +16,6 @@ export interface Props {
}
const
ContractMethodResultPublicClient
=
({
data
,
abiItem
,
onSettle
,
mode
:
modeProps
}:
Props
)
=>
{
const
bgColor
=
useColorModeValue
(
'
blackAlpha.50
'
,
'
whiteAlpha.50
'
);
React
.
useEffect
(()
=>
{
if
(
modeProps
===
'
result
'
)
{
onSettle
();
...
...
@@ -32,7 +32,7 @@ const ContractMethodResultPublicClient = ({ data, abiItem, onSettle, mode: modeP
return
(
<>
{
isError
&&
(
<
Alert
status=
"error"
mt=
{
3
}
p=
{
4
}
borderRadius=
"md"
fontSiz
e=
"sm"
wordBreak=
"break-word"
whiteSpace=
"pre-wrap"
>
<
Alert
status=
"error"
mt=
{
3
}
p=
{
4
}
borderRadius=
"md"
textStyl
e=
"sm"
wordBreak=
"break-word"
whiteSpace=
"pre-wrap"
>
{
'
shortMessage
'
in
data
&&
typeof
data
.
shortMessage
===
'
string
'
?
data
.
shortMessage
:
data
.
message
}
</
Alert
>
)
}
...
...
@@ -42,7 +42,7 @@ const ContractMethodResultPublicClient = ({ data, abiItem, onSettle, mode: modeP
mt=
{
3
}
p=
{
4
}
borderRadius=
"md"
bgColor=
{
bgColor
}
bgColor=
{
{
_light
:
'
blackAlpha.50
'
,
_dark
:
'
whiteAlpha.50
'
}
}
color=
{
mode
===
'
preview
'
?
'
gray.500
'
:
undefined
}
fontSize=
"sm"
lineHeight=
"20px"
...
...
ui/address/contract/methods/form/ContractMethodResultWalletClient.tsx
View file @
03c9e582
import
{
chakra
,
Spinner
,
Box
,
Alert
}
from
'
@chakra-ui/react
'
;
import
{
chakra
,
Spinner
,
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
UseWaitForTransactionReceiptReturnType
}
from
'
wagmi
'
;
import
{
useWaitForTransactionReceipt
}
from
'
wagmi
'
;
...
...
@@ -7,7 +7,8 @@ import type { FormSubmitResultWalletClient } from '../types';
import
{
route
}
from
'
nextjs-routes
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
{
Alert
}
from
'
toolkit/chakra/alert
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
interface
Props
{
data
:
FormSubmitResultWalletClient
[
'
data
'
];
...
...
@@ -45,13 +46,13 @@ export const ContractMethodResultWalletClientDumb = ({ data, onSettle, txInfo }:
const
isErrorResult
=
'
message
'
in
data
;
const
txLink
=
txHash
?
(
<
Link
Internal
href=
{
route
({
pathname
:
'
/tx/[hash]
'
,
query
:
{
hash
:
txHash
}
})
}
>
View transaction details
</
LinkInternal
>
<
Link
href=
{
route
({
pathname
:
'
/tx/[hash]
'
,
query
:
{
hash
:
txHash
}
})
}
>
View transaction details
</
Link
>
)
:
null
;
const
content
=
(()
=>
{
if
(
isErrorResult
)
{
return
(
<
Alert
status=
"error"
>
<
Alert
status=
"error"
textStyle=
"sm"
>
{
data
.
message
}
</
Alert
>
);
...
...
@@ -81,7 +82,7 @@ export const ContractMethodResultWalletClientDumb = ({ data, onSettle, txInfo }:
case
'
error
'
:
{
return
(
<
Alert
status=
"error"
flexDir=
"column"
alignItems=
"flex-start"
rowGap=
{
1
}
>
<
Alert
status=
"error"
textStyle=
"sm"
descriptionProps=
{
{
flexDir
:
'
column
'
,
alignItems
:
'
flex-start
'
,
rowGap
:
1
}
}
>
Error:
{
txInfo
.
error
?
txInfo
.
error
.
message
:
'
Something went wrong
'
}
{
txLink
}
</
Alert
>
);
...
...
@@ -91,7 +92,7 @@ export const ContractMethodResultWalletClientDumb = ({ data, onSettle, txInfo }:
return
(
<
Box
fontSiz
e=
"sm"
textStyl
e=
"sm"
mt=
{
3
}
alignItems=
"center"
whiteSpace=
"pre-wrap"
...
...
ui/address/contract/methods/form/resultPublicClient/ItemPrimitive.tsx
View file @
03c9e582
import
{
Tooltip
}
from
'
@chakra-ui/react
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
import
type
{
AbiParameter
}
from
'
viem
'
;
...
...
@@ -6,8 +5,9 @@ import type { AbiParameter } from 'viem';
import
{
route
}
from
'
nextjs-routes
'
;
import
{
WEI
}
from
'
lib/consts
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
Tooltip
}
from
'
toolkit/chakra/tooltip
'
;
import
CopyToClipboard
from
'
ui/shared/CopyToClipboard
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
{
matchInt
}
from
'
../utils
'
;
import
ItemLabel
from
'
./ItemLabel
'
;
...
...
@@ -44,8 +44,8 @@ const ItemPrimitive = ({ abiParameter, data, level, hideLabel }: Props) => {
if
(
abiParameter
.
type
===
'
address
'
&&
typeof
data
===
'
string
'
)
{
return
(
<>
<
Link
Internal
href=
{
route
({
pathname
:
'
/address/[hash]
'
,
query
:
{
hash
:
data
}
})
}
>
{
data
}
</
LinkInternal
>
<
CopyToClipboard
text=
{
data
}
s
ize=
{
4
}
verticalAlign=
"sub"
/>
<
Link
href=
{
route
({
pathname
:
'
/address/[hash]
'
,
query
:
{
hash
:
data
}
})
}
>
{
data
}
</
Link
>
<
CopyToClipboard
text=
{
data
}
boxS
ize=
{
4
}
verticalAlign=
"sub"
/>
</>
);
}
...
...
@@ -54,7 +54,7 @@ const ItemPrimitive = ({ abiParameter, data, level, hideLabel }: Props) => {
if
(
intMatch
&&
typeof
data
===
'
bigint
'
&&
intMatch
.
max
>
INT_TOOLTIP_THRESHOLD
&&
data
>
INT_TOOLTIP_THRESHOLD
)
{
const
dividedValue
=
BigNumber
(
data
.
toString
()).
div
(
WEI
);
return
(
<
Tooltip
label
=
{
dividedValue
.
toLocaleString
()
+
'
ETH
'
}
>
<
Tooltip
content
=
{
dividedValue
.
toLocaleString
()
+
'
ETH
'
}
>
<
span
>
{
castValueToString
(
data
)
}
</
span
>
</
Tooltip
>
);
...
...
ui/address/contract/methods/form/resultPublicClient/ItemTuple.tsx
View file @
03c9e582
...
...
@@ -16,7 +16,7 @@ interface Props {
const
ItemTuple
=
({
abiParameter
,
data
,
mode
,
level
}:
Props
)
=>
{
return
(
<
div
>
<
p
>
<
p
>
<
span
>
{
printRowOffset
(
level
)
}
</
span
>
<
chakra
.
span
fontWeight=
{
500
}
>
{
abiParameter
.
name
||
abiParameter
.
internalType
}
</
chakra
.
span
>
...
...
@@ -48,7 +48,7 @@ const ItemTuple = ({ abiParameter, data, mode, level }: Props) => {
);
})
}
<
p
>
{
printRowOffset
(
level
)
}{
'
}
'
}
</
p
>
</
div
>
</
p
>
);
};
...
...
ui/address/contract/methods/useScrollToMethod.ts
View file @
03c9e582
...
...
@@ -19,7 +19,7 @@ export const getElementName = (data: SmartContractMethod) => {
return
`method_
${
getElementId
(
data
)
}
`
;
};
export
default
function
useScrollToMethod
(
data
:
Array
<
SmartContractMethod
>
,
onScroll
:
(
indices
:
Array
<
number
>
)
=>
void
)
{
export
default
function
useScrollToMethod
(
data
:
Array
<
SmartContractMethod
>
,
onScroll
:
(
indices
:
Array
<
string
>
)
=>
void
)
{
React
.
useEffect
(()
=>
{
const
hash
=
window
.
location
.
hash
.
replace
(
'
#
'
,
''
);
...
...
@@ -34,7 +34,7 @@ export default function useScrollToMethod(data: Array<SmartContractMethod>, onSc
smooth
:
true
,
offset
:
-
100
,
});
onScroll
([
index
]);
onScroll
([
String
(
index
)
]);
}
},
[
data
,
onScroll
]);
}
ui/shared/Hint.tsx
View file @
03c9e582
...
...
@@ -11,9 +11,10 @@ interface Props {
className
?:
string
;
tooltipProps
?:
Partial
<
TooltipProps
>
;
isLoading
?:
boolean
;
as
?:
React
.
ElementType
;
}
const
Hint
=
({
label
,
className
,
tooltipProps
,
isLoading
}:
Props
)
=>
{
const
Hint
=
({
label
,
className
,
tooltipProps
,
isLoading
,
as
}:
Props
)
=>
{
return
(
<
Tooltip
content=
{
label
}
...
...
@@ -27,6 +28,7 @@ const Hint = ({ label, className, tooltipProps, isLoading }: Props) => {
className=
{
className
}
loading=
{
isLoading
}
borderRadius=
"sm"
as=
{
as
}
>
<
IconSvg
name=
"info"
w=
"100%"
h=
"100%"
color=
"icon_info"
_hover=
{
{
color
:
'
link.primary.hover
'
}
}
/>
</
IconButton
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment