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
c159bf91
Commit
c159bf91
authored
Jan 10, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
contract read fixes
parent
c9f557b8
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
125 additions
and
61 deletions
+125
-61
contract.ts
types/api/contract.ts
+24
-0
ContractConnectWallet.tsx
ui/address/contract/ContractConnectWallet.tsx
+5
-9
ContractMethodCallable.tsx
ui/address/contract/ContractMethodCallable.tsx
+27
-26
ContractMethodField.tsx
ui/address/contract/ContractMethodField.tsx
+4
-3
ContractMethodsAccordion.tsx
ui/address/contract/ContractMethodsAccordion.tsx
+1
-1
ContractRead.tsx
ui/address/contract/ContractRead.tsx
+44
-17
ContractWrite.tsx
ui/address/contract/ContractWrite.tsx
+8
-3
types.ts
ui/address/contract/types.ts
+10
-0
CodeEditor.tsx
ui/shared/CodeEditor.tsx
+2
-2
No files found.
types/api/contract.ts
View file @
c159bf91
...
...
@@ -47,3 +47,27 @@ export interface SmartContractMethodInput {
export
interface
SmartContractMethodOutput
extends
SmartContractMethodInput
{
value
?:
string
;
}
export
interface
SmartContractQueryMethodReadSuccess
{
is_error
:
false
;
result
:
{
names
:
Array
<
string
>
;
output
:
Array
<
{
type
:
string
;
value
:
string
;
}
>
;
};
}
export
interface
SmartContractQueryMethodReadError
{
is_error
:
true
;
result
:
{
code
:
number
;
message
:
string
;
raw
?:
string
;
}
|
{
error
:
string
;
};
}
export
type
SmartContractQueryMethodRead
=
SmartContractQueryMethodReadSuccess
|
SmartContractQueryMethodReadError
;
ui/address/contract/ContractConnectWallet.tsx
View file @
c159bf91
import
{
Alert
,
chakra
,
Link
}
from
'
@chakra-ui/react
'
;
import
{
Alert
,
Button
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
useWeb3Modal
}
from
'
@web3modal/react
'
;
import
React
from
'
react
'
;
import
{
useAccount
,
useDisconnect
}
from
'
wagmi
'
;
...
...
@@ -6,7 +6,7 @@ import { useAccount, useDisconnect } from 'wagmi';
import
AddressIcon
from
'
ui/shared/address/AddressIcon
'
;
const
ContractConnectWallet
=
()
=>
{
const
{
isOpen
,
open
}
=
useWeb3Modal
();
const
{
open
}
=
useWeb3Modal
();
const
{
address
,
isDisconnected
}
=
useAccount
();
const
{
disconnect
}
=
useDisconnect
();
...
...
@@ -19,15 +19,11 @@ const ContractConnectWallet = () => {
},
[
disconnect
]);
const
content
=
(()
=>
{
if
(
isOpen
)
{
return
<
span
>
connecting...
</
span
>;
}
if
(
isDisconnected
||
!
address
)
{
return
(
<>
<
span
>
Disconnected
.
</
span
>
<
Link
ml=
{
1
}
onClick=
{
handleConnect
}
>
Connect wallet
</
Link
>
<
span
>
Disconnected
</
span
>
<
Button
ml=
{
3
}
onClick=
{
handleConnect
}
size=
"sm"
variant=
"outline"
>
Connect wallet
</
Button
>
</>
);
}
...
...
@@ -37,7 +33,7 @@ const ContractConnectWallet = () => {
<
span
>
Connected to
</
span
>
<
AddressIcon
address=
{
{
hash
:
address
,
is_contract
:
false
}
}
mx=
{
2
}
/>
<
chakra
.
span
fontWeight=
{
600
}
>
{
address
}
</
chakra
.
span
>
<
Link
ml=
{
2
}
onClick=
{
handleDisconnect
}
>
Disconnect
</
Link
>
<
Button
ml=
{
3
}
onClick=
{
handleDisconnect
}
size=
"sm"
variant=
"outline"
>
Disconnect
</
Button
>
</>
);
})();
...
...
ui/address/contract/ContractMethodCallable.tsx
View file @
c159bf91
import
{
Box
,
Button
,
chakra
,
Flex
,
Icon
,
Text
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Button
,
chakra
,
Flex
,
Icon
,
Text
}
from
'
@chakra-ui/react
'
;
import
_fromPairs
from
'
lodash/fromPairs
'
;
import
React
from
'
react
'
;
import
type
{
SubmitHandler
}
from
'
react-hook-form
'
;
import
{
useForm
}
from
'
react-hook-form
'
;
import
type
{
MethodFormFields
}
from
'
./types
'
;
import
type
{
MethodFormFields
,
ContractMethodCallResult
}
from
'
./types
'
;
import
type
{
SmartContractMethodInput
,
SmartContractMethod
}
from
'
types/api/contract
'
;
import
appConfig
from
'
configs/app/config
'
;
...
...
@@ -14,7 +14,8 @@ import ContractMethodField from './ContractMethodField';
interface
Props
<
T
extends
SmartContractMethod
>
{
data
:
T
;
caller
:
(
data
:
T
,
args
:
Array
<
string
>
)
=>
Promise
<
Array
<
Array
<
string
>>
|
undefined
>
;
onSubmit
:
(
data
:
T
,
args
:
Array
<
string
>
)
=>
Promise
<
ContractMethodCallResult
<
T
>>
;
renderResult
:
(
data
:
T
,
result
:
ContractMethodCallResult
<
T
>
)
=>
React
.
ReactNode
;
isWrite
?:
boolean
;
}
...
...
@@ -36,7 +37,10 @@ const sortFields = (data: Array<SmartContractMethodInput>) => ([ a ]: [string, s
return
0
;
};
const
ContractMethodCallable
=
<
T
extends
SmartContractMethod
>
(
{
data
,
caller
,
isWrite
}
: Props
<
T
>
) =
>
{
const
ContractMethodCallable
=
<
T
extends
SmartContractMethod
>
(
{
data
,
onSubmit
,
renderResult
,
isWrite
}
: Props
<
T
>
) =
>
{
const
[
result
,
setResult
]
=
React
.
useState
<
ContractMethodCallResult
<
T
>>
();
const
[
isLoading
,
setLoading
]
=
React
.
useState
(
false
);
const
inputs
=
React
.
useMemo
(()
=>
{
return
data
.
payable
&&
(
!
(
'
inputs
'
in
data
)
||
data
.
inputs
.
length
===
0
)
?
[
{
...
...
@@ -49,19 +53,24 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, caller, i
const
{
control
,
handleSubmit
,
setValue
}
=
useForm
<
MethodFormFields
>
({
defaultValues
:
_fromPairs
(
inputs
.
map
(({
name
},
index
)
=>
[
getFieldName
(
name
,
index
),
''
])),
});
const
[
result
,
setResult
]
=
React
.
useState
<
Array
<
Array
<
string
>>>
([
]);
const
onSubmit
:
SubmitHandler
<
MethodFormFields
>
=
React
.
useCallback
(
async
(
formData
)
=>
{
const
on
Form
Submit
:
SubmitHandler
<
MethodFormFields
>
=
React
.
useCallback
(
async
(
formData
)
=>
{
const
args
=
Object
.
entries
(
formData
)
.
sort
(
sortFields
(
inputs
))
.
map
(([
,
value
])
=>
value
);
const
result
=
await
caller
(
data
,
args
);
result
&&
setResult
(
result
);
},
[
caller
,
data
,
inputs
]);
const
resultBgColor
=
useColorModeValue
(
'
blackAlpha.50
'
,
'
whiteAlpha.50
'
);
setResult
(
undefined
);
setLoading
(
true
);
onSubmit
(
data
,
args
)
.
then
((
result
)
=>
{
setResult
(
result
);
setLoading
(
false
);
})
.
catch
((
error
)
=>
{
setResult
(
error
);
setLoading
(
false
);
});
},
[
onSubmit
,
data
,
inputs
]);
return
(
<
Box
>
...
...
@@ -72,7 +81,7 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, caller, i
flexDir=
{
{
base
:
'
column
'
,
lg
:
'
row
'
}
}
rowGap=
{
2
}
alignItems=
{
{
base
:
'
flex-start
'
,
lg
:
'
center
'
}
}
onSubmit=
{
handleSubmit
(
onSubmit
)
}
onSubmit=
{
handleSubmit
(
on
Form
Submit
)
}
flexWrap=
"wrap"
>
{
inputs
.
map
(({
type
,
name
},
index
)
=>
{
...
...
@@ -84,10 +93,13 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, caller, i
placeholder=
{
`${ name }(${ type })`
}
control=
{
control
}
setValue=
{
setValue
}
isDisabled=
{
isLoading
}
/>
);
})
}
<
Button
isLoading=
{
isLoading
}
loadingText=
{
isWrite
?
'
Write
'
:
'
Query
'
}
variant=
"outline"
size=
"sm"
flexShrink=
{
0
}
...
...
@@ -102,18 +114,7 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, caller, i
<
Text
>
{
data
.
outputs
.
map
(({
type
})
=>
type
).
join
(
'
,
'
)
}
</
Text
>
</
Flex
>
)
}
{
result
.
length
>
0
&&
(
<
Box
mt=
{
3
}
p=
{
4
}
borderRadius=
"md"
bgColor=
{
resultBgColor
}
fontSize=
"sm"
>
<
p
>
[
<
chakra
.
span
fontWeight=
{
600
}
>
{
'
name
'
in
data
?
data
.
name
:
''
}
</
chakra
.
span
>
method response ]
</
p
>
<
p
>
[
</
p
>
{
result
.
map
(([
key
,
value
],
index
)
=>
(
<
chakra
.
p
key=
{
index
}
whiteSpace=
"break-spaces"
wordBreak=
"break-all"
>
{
key
}
:
{
value
}
</
chakra
.
p
>
))
}
<
p
>
]
</
p
>
</
Box
>
)
}
{
result
&&
renderResult
(
data
,
result
)
}
</
Box
>
);
}
;
...
...
ui/address/contract/ContractMethodField.tsx
View file @
c159bf91
...
...
@@ -12,9 +12,10 @@ interface Props {
setValue
:
UseFormSetValue
<
MethodFormFields
>
;
placeholder
:
string
;
name
:
string
;
isDisabled
:
boolean
;
}
const
ContractMethodField
=
({
control
,
name
,
placeholder
,
setValue
}:
Props
)
=>
{
const
ContractMethodField
=
({
control
,
name
,
placeholder
,
setValue
,
isDisabled
}:
Props
)
=>
{
const
ref
=
React
.
useRef
<
HTMLInputElement
>
(
null
);
const
handleClear
=
React
.
useCallback
(()
=>
{
...
...
@@ -24,7 +25,7 @@ const ContractMethodField = ({ control, name, placeholder, setValue }: Props) =>
const
renderInput
=
React
.
useCallback
(({
field
}:
{
field
:
ControllerRenderProps
<
MethodFormFields
>
})
=>
{
return
(
<
FormControl
id=
{
name
}
maxW=
{
{
base
:
'
100%
'
,
lg
:
'
calc((100% - 24px) / 3)
'
}
}
>
<
FormControl
id=
{
name
}
maxW=
{
{
base
:
'
100%
'
,
lg
:
'
calc((100% - 24px) / 3)
'
}
}
isDisabled=
{
isDisabled
}
>
<
InputGroup
size=
"xs"
>
<
Input
{
...
field
}
...
...
@@ -39,7 +40,7 @@ const ContractMethodField = ({ control, name, placeholder, setValue }: Props) =>
</
InputGroup
>
</
FormControl
>
);
},
[
handleClear
,
name
,
placeholder
]);
},
[
handleClear
,
isDisabled
,
name
,
placeholder
]);
return
(
<
Controller
...
...
ui/address/contract/ContractMethodsAccordion.tsx
View file @
c159bf91
...
...
@@ -39,7 +39,7 @@ const ContractMethodsAccordion = <T extends SmartContractMethod>({ data, renderC
<
Accordion
allowMultiple
position=
"relative"
onChange=
{
handleAccordionStateChange
}
index=
{
expandedSections
}
>
{
data
.
map
((
item
,
index
)
=>
{
return
(
<
AccordionItem
key=
{
index
}
as=
"section"
>
<
AccordionItem
key=
{
index
}
as=
"section"
_first=
{
{
borderTopWidth
:
'
0
'
}
}
>
<
h2
>
<
AccordionButton
px=
{
0
}
py=
{
3
}
_hover=
{
{
bgColor
:
'
inherit
'
}
}
>
<
Box
as=
"span"
fontFamily=
"heading"
fontWeight=
{
500
}
fontSize=
"lg"
mr=
{
1
}
>
...
...
ui/address/contract/ContractRead.tsx
View file @
c159bf91
import
{
Flex
}
from
'
@chakra-ui/react
'
;
import
{
Alert
,
Box
,
chakra
,
Flex
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
{
useAccount
}
from
'
wagmi
'
;
import
type
{
SmartContractReadMethod
}
from
'
types/api/contract
'
;
import
type
{
ContractMethodReadResult
}
from
'
./types
'
;
import
type
{
SmartContractReadMethod
,
SmartContractQueryMethodRead
}
from
'
types/api/contract
'
;
import
useApiFetch
from
'
lib/api/useApiFetch
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
...
...
@@ -10,7 +12,7 @@ import ContractMethodsAccordion from 'ui/address/contract/ContractMethodsAccordi
import
ContentLoader
from
'
ui/shared/ContentLoader
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
{
useContractContext
}
from
'
./contex
t
'
;
import
ContractConnectWallet
from
'
./ContractConnectWalle
t
'
;
import
ContractMethodCallable
from
'
./ContractMethodCallable
'
;
import
ContractMethodConstant
from
'
./ContractMethodConstant
'
;
...
...
@@ -21,6 +23,7 @@ interface Props {
const
ContractRead
=
({
isProxy
}:
Props
)
=>
{
const
router
=
useRouter
();
const
apiFetch
=
useApiFetch
();
const
{
address
:
userAddress
}
=
useAccount
();
const
addressHash
=
router
.
query
.
id
?.
toString
();
...
...
@@ -31,10 +34,8 @@ const ContractRead = ({ isProxy }: Props) => {
},
});
const
contract
=
useContractContext
();
const
contractCaller
=
React
.
useCallback
(
async
(
item
:
SmartContractReadMethod
,
args
:
Array
<
string
>
)
=>
{
await
apiFetch
(
'
contract_method_query
'
,
{
const
handleMethodFormSubmit
=
React
.
useCallback
(
async
(
item
:
SmartContractReadMethod
,
args
:
Array
<
string
>
)
=>
{
return
apiFetch
<
'
contract_method_query
'
,
SmartContractQueryMethodRead
>
(
'
contract_method_query
'
,
{
pathParams
:
{
id
:
addressHash
},
fetchParams
:
{
method
:
'
POST
'
,
...
...
@@ -42,20 +43,40 @@ const ContractRead = ({ isProxy }: Props) => {
args
,
method_id
:
item
.
method_id
,
contract_type
:
isProxy
?
'
proxy
'
:
'
regular
'
,
from
:
userAddress
,
},
},
});
},
[
addressHash
,
apiFetch
,
isProxy
,
userAddress
]);
const
resultBgColor
=
useColorModeValue
(
'
blackAlpha.50
'
,
'
whiteAlpha.50
'
);
const
result
=
await
contract
?.
functions
[
item
.
name
](...
args
);
const
renderResult
=
React
.
useCallback
((
item
:
SmartContractReadMethod
,
result
:
ContractMethodReadResult
)
=>
{
if
(
'
status
'
in
result
)
{
return
<
Alert
status=
"error"
mt=
{
3
}
p=
{
4
}
borderRadius=
"md"
fontSize=
"sm"
>
{
result
.
statusText
}
</
Alert
>;
}
// eslint-disable-next-line no-console
console
.
log
(
'
__>__
'
,
{
result
});
if
(
result
.
is_error
)
{
const
message
=
'
error
'
in
result
.
result
?
result
.
result
.
error
:
result
.
result
.
message
;
return
<
Alert
status=
"error"
mt=
{
3
}
p=
{
4
}
borderRadius=
"md"
fontSize=
"sm"
>
{
message
}
</
Alert
>;
}
return
[
[
'
string
'
,
'
this is mock
'
]
];
},
[
addressHash
,
apiFetch
,
contract
,
isProxy
]);
return
(
<
Box
mt=
{
3
}
p=
{
4
}
borderRadius=
"md"
bgColor=
{
resultBgColor
}
fontSize=
"sm"
>
<
p
>
[
<
chakra
.
span
fontWeight=
{
600
}
>
{
'
name
'
in
item
?
item
.
name
:
''
}
</
chakra
.
span
>
method response ]
</
p
>
<
p
>
[
</
p
>
{
result
.
result
.
output
.
map
(({
type
,
value
},
index
)
=>
(
<
chakra
.
p
key=
{
index
}
whiteSpace=
"break-spaces"
wordBreak=
"break-all"
>
{
type
}
:
{
String
(
value
)
}
</
chakra
.
p
>
))
}
<
p
>
]
</
p
>
</
Box
>
);
},
[
resultBgColor
]);
const
renderContent
=
React
.
useCallback
((
item
:
SmartContractReadMethod
,
index
:
number
,
id
:
number
)
=>
{
if
(
item
.
inputs
.
length
===
0
)
{
if
(
item
.
outputs
.
some
(({
value
})
=>
value
)
)
{
return
(
<
Flex
flexDir=
"column"
rowGap=
{
1
}
>
{
item
.
outputs
.
map
((
output
,
index
)
=>
<
ContractMethodConstant
key=
{
index
}
data=
{
output
}
/>)
}
...
...
@@ -67,10 +88,11 @@ const ContractRead = ({ isProxy }: Props) => {
<
ContractMethodCallable
key=
{
id
+
'
_
'
+
index
}
data=
{
item
}
caller=
{
contractCaller
}
onSubmit=
{
handleMethodFormSubmit
}
renderResult=
{
renderResult
}
/>
);
},
[
contractCaller
]);
},
[
handleMethodFormSubmit
,
renderResult
]);
if
(
isError
)
{
return
<
DataFetchAlert
/>;
...
...
@@ -80,7 +102,12 @@ const ContractRead = ({ isProxy }: Props) => {
return
<
ContentLoader
/>;
}
return
<
ContractMethodsAccordion
data=
{
data
}
renderContent=
{
renderContent
}
/>;
return
(
<>
<
ContractConnectWallet
/>
<
ContractMethodsAccordion
data=
{
data
}
renderContent=
{
renderContent
}
/>
</>
);
};
export
default
ContractRead
;
export
default
React
.
memo
(
ContractRead
)
;
ui/address/contract/ContractWrite.tsx
View file @
c159bf91
...
...
@@ -30,7 +30,7 @@ const ContractWrite = ({ isProxy }: Props) => {
const
contract
=
useContractContext
();
const
contractCaller
=
React
.
useCallback
(
async
(
item
:
SmartContractWriteMethod
,
args
:
Array
<
string
>
)
=>
{
const
handleMethodFormSubmit
=
React
.
useCallback
(
async
(
item
:
SmartContractWriteMethod
,
args
:
Array
<
string
>
)
=>
{
if
(
!
contract
)
{
return
;
}
...
...
@@ -50,16 +50,21 @@ const ContractWrite = ({ isProxy }: Props) => {
return
[
[
'
string
'
,
'
this is mock
'
]
];
},
[
contract
]);
const
renderResult
=
React
.
useCallback
(()
=>
{
return
<
span
>
result
</
span
>;
},
[]);
const
renderContent
=
React
.
useCallback
((
item
:
SmartContractWriteMethod
,
index
:
number
,
id
:
number
)
=>
{
return
(
<
ContractMethodCallable
key=
{
id
+
'
_
'
+
index
}
data=
{
item
}
caller=
{
contractCaller
}
onSubmit=
{
handleMethodFormSubmit
}
renderResult=
{
renderResult
}
isWrite
/>
);
},
[
contractCaller
]);
},
[
handleMethodFormSubmit
,
renderResult
]);
if
(
isError
)
{
return
<
DataFetchAlert
/>;
...
...
ui/address/contract/types.ts
View file @
c159bf91
import
type
{
SmartContractQueryMethodRead
,
SmartContractMethod
}
from
'
types/api/contract
'
;
import
type
{
ResourceError
}
from
'
lib/api/resources
'
;
export
type
MethodFormFields
=
Record
<
string
,
string
>
;
export
type
ContractMethodReadResult
=
SmartContractQueryMethodRead
|
ResourceError
;
export
type
ContractMethodWriteResult
=
unknown
;
export
type
ContractMethodCallResult
<
T
extends
SmartContractMethod
>
=
T
extends
{
method_id
:
string
}
?
ContractMethodReadResult
:
ContractMethodWriteResult
;
ui/shared/CodeEditor.tsx
View file @
c159bf91
import
{
chakra
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
AceEditor
from
'
react-ace
'
;
import
'
ace-builds/src-noconflict/mode-
javascript
'
;
import
'
ace-builds/src-noconflict/mode-
csharp
'
;
import
'
ace-builds/src-noconflict/theme-tomorrow
'
;
import
'
ace-builds/src-noconflict/theme-tomorrow_night
'
;
import
'
ace-builds/src-noconflict/ext-language_tools
'
;
...
...
@@ -19,7 +19,7 @@ const CodeEditorBase = chakra(({ id, value, className }: Props) => {
return
(
<
AceEditor
className=
{
className
}
mode=
"
javascript
"
// TODO need to find mode for solidity
mode=
"
csharp
"
// TODO need to find mode for solidity
theme=
{
theme
}
value=
{
value
}
name=
{
id
}
...
...
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