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
7c00d780
Commit
7c00d780
authored
Feb 01, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
form config
parent
988d3f6f
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
177 additions
and
97 deletions
+177
-97
resources.ts
lib/api/resources.ts
+5
-1
contract.ts
types/api/contract.ts
+16
-0
ContractVerificationForm.pw.tsx
ui/contractVerification/ContractVerificationForm.pw.tsx
+45
-5
ContractVerificationForm.tsx
ui/contractVerification/ContractVerificationForm.tsx
+20
-14
ContractVerificationFieldCompiler.tsx
...Verification/fields/ContractVerificationFieldCompiler.tsx
+15
-45
ContractVerificationFieldEvmVersion.tsx
...rification/fields/ContractVerificationFieldEvmVersion.tsx
+11
-8
ContractVerificationFieldMethod.tsx
...ctVerification/fields/ContractVerificationFieldMethod.tsx
+10
-16
types.ts
ui/contractVerification/types.ts
+3
-5
utils.ts
ui/contractVerification/utils.ts
+13
-0
ContractVerification.tsx
ui/pages/ContractVerification.tsx
+39
-3
No files found.
lib/api/resources.ts
View file @
7c00d780
...
@@ -17,7 +17,7 @@ import type {
...
@@ -17,7 +17,7 @@ import type {
import
type
{
AddressesResponse
}
from
'
types/api/addresses
'
;
import
type
{
AddressesResponse
}
from
'
types/api/addresses
'
;
import
type
{
BlocksResponse
,
BlockTransactionsResponse
,
Block
,
BlockFilters
}
from
'
types/api/block
'
;
import
type
{
BlocksResponse
,
BlockTransactionsResponse
,
Block
,
BlockFilters
}
from
'
types/api/block
'
;
import
type
{
ChartMarketResponse
,
ChartTransactionResponse
}
from
'
types/api/charts
'
;
import
type
{
ChartMarketResponse
,
ChartTransactionResponse
}
from
'
types/api/charts
'
;
import
type
{
SmartContract
,
SmartContractReadMethod
,
SmartContractWriteMethod
}
from
'
types/api/contract
'
;
import
type
{
SmartContract
,
SmartContractReadMethod
,
SmartContractWriteMethod
,
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
type
{
IndexingStatus
}
from
'
types/api/indexingStatus
'
;
import
type
{
IndexingStatus
}
from
'
types/api/indexingStatus
'
;
import
type
{
InternalTransactionsResponse
}
from
'
types/api/internalTransaction
'
;
import
type
{
InternalTransactionsResponse
}
from
'
types/api/internalTransaction
'
;
import
type
{
LogsResponseTx
,
LogsResponseAddress
}
from
'
types/api/log
'
;
import
type
{
LogsResponseTx
,
LogsResponseAddress
}
from
'
types/api/log
'
;
...
@@ -204,6 +204,9 @@ export const RESOURCES = {
...
@@ -204,6 +204,9 @@ export const RESOURCES = {
contract_methods_write_proxy
:
{
contract_methods_write_proxy
:
{
path
:
'
/api/v2/smart-contracts/:id/methods-write-proxy
'
,
path
:
'
/api/v2/smart-contracts/:id/methods-write-proxy
'
,
},
},
contract_verification_config
:
{
path
:
'
/api/v2/smart-contracts/verification/config
'
,
},
// TOKEN
// TOKEN
token
:
{
token
:
{
...
@@ -356,6 +359,7 @@ Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> :
...
@@ -356,6 +359,7 @@ Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> :
Q
extends
'
contract_methods_read_proxy
'
?
Array
<
SmartContractReadMethod
>
:
Q
extends
'
contract_methods_read_proxy
'
?
Array
<
SmartContractReadMethod
>
:
Q
extends
'
contract_methods_write
'
?
Array
<
SmartContractWriteMethod
>
:
Q
extends
'
contract_methods_write
'
?
Array
<
SmartContractWriteMethod
>
:
Q
extends
'
contract_methods_write_proxy
'
?
Array
<
SmartContractWriteMethod
>
:
Q
extends
'
contract_methods_write_proxy
'
?
Array
<
SmartContractWriteMethod
>
:
Q
extends
'
contract_verification_config
'
?
SmartContractVerificationConfig
:
never
;
never
;
/* eslint-enable @typescript-eslint/indent */
/* eslint-enable @typescript-eslint/indent */
...
...
types/api/contract.ts
View file @
7c00d780
...
@@ -113,3 +113,19 @@ export interface SmartContractQueryMethodReadError {
...
@@ -113,3 +113,19 @@ export interface SmartContractQueryMethodReadError {
}
}
export
type
SmartContractQueryMethodRead
=
SmartContractQueryMethodReadSuccess
|
SmartContractQueryMethodReadError
;
export
type
SmartContractQueryMethodRead
=
SmartContractQueryMethodReadSuccess
|
SmartContractQueryMethodReadError
;
// VERIFICATION
export
type
SmartContractVerificationMethod
=
'
flattened_code
'
|
'
standard_input
'
|
'
sourcify
'
|
'
multi_part
'
|
'
vyper_multi_part
'
;
export
interface
SmartContractVerificationConfigRaw
{
solidity_compiler_versions
:
Array
<
string
>
;
solidity_evm_versions
:
Array
<
string
>
;
verification_options
:
Array
<
string
>
;
vyper_compiler_versions
:
Array
<
string
>
;
vyper_evm_versions
:
Array
<
string
>
;
}
export
interface
SmartContractVerificationConfig
extends
SmartContractVerificationConfigRaw
{
verification_options
:
Array
<
SmartContractVerificationMethod
>
;
}
ui/contractVerification/ContractVerificationForm.pw.tsx
View file @
7c00d780
import
{
test
,
expect
}
from
'
@playwright/experimental-ct-react
'
;
import
{
test
,
expect
}
from
'
@playwright/experimental-ct-react
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
TestApp
from
'
playwright/TestApp
'
;
import
TestApp
from
'
playwright/TestApp
'
;
import
ContractVerificationForm
from
'
./ContractVerificationForm
'
;
import
ContractVerificationForm
from
'
./ContractVerificationForm
'
;
...
@@ -11,10 +13,48 @@ const hooksConfig = {
...
@@ -11,10 +13,48 @@ const hooksConfig = {
},
},
};
};
const
formConfig
:
SmartContractVerificationConfig
=
{
solidity_compiler_versions
:
[
'
v0.8.17+commit.8df45f5f
'
,
'
v0.8.16+commit.07a7930e
'
,
'
v0.8.15+commit.e14f2714
'
,
'
v0.8.18-nightly.2022.11.23+commit.eb2f874e
'
,
'
v0.8.17-nightly.2022.8.24+commit.22a0c46e
'
,
'
v0.8.16-nightly.2022.7.6+commit.b6f11b33
'
,
],
solidity_evm_versions
:
[
'
default
'
,
'
london
'
,
'
berlin
'
,
],
verification_options
:
[
'
flattened_code
'
,
'
standard_input
'
,
'
sourcify
'
,
'
multi_part
'
,
'
vyper_multi_part
'
,
],
vyper_compiler_versions
:
[
'
v0.3.7+commit.6020b8bb
'
,
'
v0.3.1+commit.0463ea4c
'
,
'
v0.3.0+commit.8a23feb
'
,
'
v0.2.16+commit.59e1bdd
'
,
'
v0.2.3+commit.006968f
'
,
'
v0.2.2+commit.337c2ef
'
,
'
v0.1.0-beta.17+commit.0671b7b
'
,
],
vyper_evm_versions
:
[
'
byzantium
'
,
'
constantinople
'
,
'
petersburg
'
,
'
istanbul
'
,
],
};
test
(
'
flatten source code method +@dark-mode +@mobile
'
,
async
({
mount
,
page
})
=>
{
test
(
'
flatten source code method +@dark-mode +@mobile
'
,
async
({
mount
,
page
})
=>
{
const
component
=
await
mount
(
const
component
=
await
mount
(
<
TestApp
>
<
TestApp
>
<
ContractVerificationForm
/>
<
ContractVerificationForm
config=
{
formConfig
}
/>
</
TestApp
>,
</
TestApp
>,
{
hooksConfig
},
{
hooksConfig
},
);
);
...
@@ -30,7 +70,7 @@ test('flatten source code method +@dark-mode +@mobile', async({ mount, page }) =
...
@@ -30,7 +70,7 @@ test('flatten source code method +@dark-mode +@mobile', async({ mount, page }) =
test
(
'
standard input json method
'
,
async
({
mount
,
page
})
=>
{
test
(
'
standard input json method
'
,
async
({
mount
,
page
})
=>
{
const
component
=
await
mount
(
const
component
=
await
mount
(
<
TestApp
>
<
TestApp
>
<
ContractVerificationForm
/>
<
ContractVerificationForm
config=
{
formConfig
}
/>
</
TestApp
>,
</
TestApp
>,
{
hooksConfig
},
{
hooksConfig
},
);
);
...
@@ -43,7 +83,7 @@ test('standard input json method', async({ mount, page }) => {
...
@@ -43,7 +83,7 @@ test('standard input json method', async({ mount, page }) => {
test
(
'
sourcify method +@dark-mode +@mobile
'
,
async
({
mount
,
page
})
=>
{
test
(
'
sourcify method +@dark-mode +@mobile
'
,
async
({
mount
,
page
})
=>
{
const
component
=
await
mount
(
const
component
=
await
mount
(
<
TestApp
>
<
TestApp
>
<
ContractVerificationForm
/>
<
ContractVerificationForm
config=
{
formConfig
}
/>
</
TestApp
>,
</
TestApp
>,
{
hooksConfig
},
{
hooksConfig
},
);
);
...
@@ -62,7 +102,7 @@ test('sourcify method +@dark-mode +@mobile', async({ mount, page }) => {
...
@@ -62,7 +102,7 @@ test('sourcify method +@dark-mode +@mobile', async({ mount, page }) => {
test
(
'
multi-part files method
'
,
async
({
mount
,
page
})
=>
{
test
(
'
multi-part files method
'
,
async
({
mount
,
page
})
=>
{
const
component
=
await
mount
(
const
component
=
await
mount
(
<
TestApp
>
<
TestApp
>
<
ContractVerificationForm
/>
<
ContractVerificationForm
config=
{
formConfig
}
/>
</
TestApp
>,
</
TestApp
>,
{
hooksConfig
},
{
hooksConfig
},
);
);
...
@@ -75,7 +115,7 @@ test('multi-part files method', async({ mount, page }) => {
...
@@ -75,7 +115,7 @@ test('multi-part files method', async({ mount, page }) => {
test
(
'
vyper contract method
'
,
async
({
mount
,
page
})
=>
{
test
(
'
vyper contract method
'
,
async
({
mount
,
page
})
=>
{
const
component
=
await
mount
(
const
component
=
await
mount
(
<
TestApp
>
<
TestApp
>
<
ContractVerificationForm
/>
<
ContractVerificationForm
config=
{
formConfig
}
/>
</
TestApp
>,
</
TestApp
>,
{
hooksConfig
},
{
hooksConfig
},
);
);
...
...
ui/contractVerification/ContractVerificationForm.tsx
View file @
7c00d780
import
{
Button
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
Button
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
SubmitHandler
}
from
'
react-hook-form
'
;
import
type
{
SubmitHandler
}
from
'
react-hook-form
'
;
import
{
useForm
,
FormProvider
}
from
'
react-hook-form
'
;
import
{
useForm
,
FormProvider
}
from
'
react-hook-form
'
;
import
type
{
FormFields
,
VerificationMethod
}
from
'
./types
'
;
import
type
{
FormFields
}
from
'
./types
'
;
import
type
{
SmartContractVerificationMethod
,
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
delay
from
'
lib/delay
'
;
import
delay
from
'
lib/delay
'
;
import
ContractVerificationFieldMethod
,
{
VERIFICATION_METHODS
}
from
'
./fields/ContractVerificationFieldMethod
'
;
import
ContractVerificationFieldMethod
from
'
./fields/ContractVerificationFieldMethod
'
;
import
ContractVerificationFlattenSourceCode
from
'
./methods/ContractVerificationFlattenSourceCode
'
;
import
ContractVerificationFlattenSourceCode
from
'
./methods/ContractVerificationFlattenSourceCode
'
;
import
ContractVerificationMultiPartFile
from
'
./methods/ContractVerificationMultiPartFile
'
;
import
ContractVerificationMultiPartFile
from
'
./methods/ContractVerificationMultiPartFile
'
;
import
ContractVerificationSourcify
from
'
./methods/ContractVerificationSourcify
'
;
import
ContractVerificationSourcify
from
'
./methods/ContractVerificationSourcify
'
;
import
ContractVerificationStandardInput
from
'
./methods/ContractVerificationStandardInput
'
;
import
ContractVerificationStandardInput
from
'
./methods/ContractVerificationStandardInput
'
;
import
ContractVerificationVyperContract
from
'
./methods/ContractVerificationVyperContract
'
;
import
ContractVerificationVyperContract
from
'
./methods/ContractVerificationVyperContract
'
;
const
METHODS
=
{
const
METHOD
_COMPONENT
S
=
{
flatten
_source
_code
:
<
ContractVerificationFlattenSourceCode
/>,
flatten
ed
_code
:
<
ContractVerificationFlattenSourceCode
/>,
standard_input
:
<
ContractVerificationStandardInput
/>,
standard_input
:
<
ContractVerificationStandardInput
/>,
sourcify
:
<
ContractVerificationSourcify
/>,
sourcify
:
<
ContractVerificationSourcify
/>,
multi_part
_file
:
<
ContractVerificationMultiPartFile
/>,
multi_part
:
<
ContractVerificationMultiPartFile
/>,
vyper_
contrac
t
:
<
ContractVerificationVyperContract
/>,
vyper_
multi_par
t
:
<
ContractVerificationVyperContract
/>,
};
};
const
ContractVerificationForm
=
()
=>
{
interface
Props
{
const
router
=
useRouter
();
method
?:
SmartContractVerificationMethod
;
const
methodFromQuery
=
router
.
query
.
method
?.
toString
()
as
VerificationMethod
;
config
:
SmartContractVerificationConfig
;
}
const
ContractVerificationForm
=
({
method
:
methodFromQuery
,
config
}:
Props
)
=>
{
const
formApi
=
useForm
<
FormFields
>
({
const
formApi
=
useForm
<
FormFields
>
({
mode
:
'
onBlur
'
,
mode
:
'
onBlur
'
,
defaultValues
:
{
defaultValues
:
{
method
:
VERIFICATION_METHODS
.
includes
(
methodFromQuery
)
?
methodFromQuery
:
undefined
,
method
:
methodFromQuery
,
},
},
});
});
const
{
control
,
handleSubmit
,
watch
,
formState
}
=
formApi
;
const
{
control
,
handleSubmit
,
watch
,
formState
}
=
formApi
;
...
@@ -42,16 +45,19 @@ const ContractVerificationForm = () => {
...
@@ -42,16 +45,19 @@ const ContractVerificationForm = () => {
const
method
=
watch
(
'
method
'
);
const
method
=
watch
(
'
method
'
);
const
content
=
METHODS
[
method
]
||
null
;
const
content
=
METHOD
_COMPONENT
S
[
method
]
||
null
;
return
(
return
(
<
FormProvider
{
...
formApi
}
>
<
FormProvider
{
...
formApi
}
>
<
chakra
.
form
<
chakra
.
form
noValidate
noValidate
onSubmit=
{
handleSubmit
(
onFormSubmit
)
}
onSubmit=
{
handleSubmit
(
onFormSubmit
)
}
mt=
{
12
}
>
>
<
ContractVerificationFieldMethod
control=
{
control
}
isDisabled=
{
Boolean
(
method
)
}
/>
<
ContractVerificationFieldMethod
control=
{
control
}
isDisabled=
{
Boolean
(
method
)
}
methods=
{
config
.
verification_options
}
/>
{
content
}
{
content
}
{
Boolean
(
method
)
&&
(
{
Boolean
(
method
)
&&
(
<
Button
<
Button
...
...
ui/contractVerification/fields/ContractVerificationFieldCompiler.tsx
View file @
7c00d780
import
{
Code
,
Checkbox
}
from
'
@chakra-ui/react
'
;
import
{
Code
}
from
'
@chakra-ui/react
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
type
{
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
{
useFormContext
,
Controller
}
from
'
react-hook-form
'
;
import
{
useFormContext
,
Controller
}
from
'
react-hook-form
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
type
{
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
FancySelect
from
'
ui/shared/FancySelect/FancySelect
'
;
import
FancySelect
from
'
ui/shared/FancySelect/FancySelect
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
const
COMPILERS
=
[
'
v0.8.17+commit.8df45f5f
'
,
'
v0.8.16+commit.07a7930e
'
,
'
v0.8.15+commit.e14f2714
'
,
];
const
COMPILERS_NIGHTLY
=
[
'
v0.8.18-nightly.2022.11.23+commit.eb2f874e
'
,
'
v0.8.17-nightly.2022.8.24+commit.22a0c46e
'
,
'
v0.8.16-nightly.2022.7.6+commit.b6f11b33
'
,
];
interface
Props
{
interface
Props
{
isVyper
?:
boolean
;
isVyper
?:
boolean
;
}
}
const
ContractVerificationFieldCompiler
=
({
isVyper
}:
Props
)
=>
{
const
ContractVerificationFieldCompiler
=
({
isVyper
}:
Props
)
=>
{
const
[
isNightly
,
setIsNightly
]
=
React
.
useState
(
false
);
const
{
formState
,
control
}
=
useFormContext
<
FormFields
>
();
const
{
formState
,
control
,
getValues
,
resetField
}
=
useFormContext
<
FormFields
>
();
const
isMobile
=
useIsMobile
();
const
isMobile
=
useIsMobile
();
const
queryClient
=
useQueryClient
();
const
config
=
queryClient
.
getQueryData
<
SmartContractVerificationConfig
>
(
getResourceKey
(
'
contract_verification_config
'
));
const
options
=
React
.
useMemo
(()
=>
(
const
options
=
React
.
useMemo
(()
=>
(
[
(
isVyper
?
config
?.
vyper_compiler_versions
:
config
?.
solidity_compiler_versions
)?.
map
((
option
)
=>
({
label
:
option
,
value
:
option
}))
||
[]
...
COMPILERS
,
...(
isNightly
?
COMPILERS_NIGHTLY
:
[]),
),
[
config
?.
solidity_compiler_versions
,
config
?.
vyper_compiler_versions
,
isVyper
]);
].
map
((
option
)
=>
({
label
:
option
,
value
:
option
}))
),
[
isNightly
]);
const
handleCheckboxChange
=
React
.
useCallback
(()
=>
{
if
(
isNightly
)
{
const
field
=
getValues
(
'
compiler
'
);
field
.
value
.
includes
(
'
nightly
'
)
&&
resetField
(
'
compiler
'
,
{
defaultValue
:
null
});
}
setIsNightly
(
prev
=>
!
prev
);
},
[
getValues
,
isNightly
,
resetField
]);
const
renderControl
=
React
.
useCallback
(({
field
}:
{
field
:
ControllerRenderProps
<
FormFields
,
'
compiler
'
>
})
=>
{
const
renderControl
=
React
.
useCallback
(({
field
}:
{
field
:
ControllerRenderProps
<
FormFields
,
'
compiler
'
>
})
=>
{
const
error
=
'
compiler
'
in
formState
.
errors
?
formState
.
errors
.
compiler
:
undefined
;
const
error
=
'
compiler
'
in
formState
.
errors
?
formState
.
errors
.
compiler
:
undefined
;
...
@@ -63,24 +45,12 @@ const ContractVerificationFieldCompiler = ({ isVyper }: Props) => {
...
@@ -63,24 +45,12 @@ const ContractVerificationFieldCompiler = ({ isVyper }: Props) => {
return
(
return
(
<
ContractVerificationFormRow
>
<
ContractVerificationFormRow
>
<>
<
Controller
<
Controller
name=
"compiler"
name=
"compiler"
control=
{
control
}
control=
{
control
}
render=
{
renderControl
}
render=
{
renderControl
}
rules=
{
{
required
:
true
}
}
rules=
{
{
required
:
true
}
}
/>
/>
{
!
isVyper
&&
(
<
Checkbox
size=
"lg"
mt=
{
3
}
onChange=
{
handleCheckboxChange
}
isDisabled=
{
formState
.
isSubmitting
}
>
Include nightly builds
</
Checkbox
>
)
}
</>
{
isVyper
?
null
:
(
{
isVyper
?
null
:
(
<>
<>
<
span
>
The compiler version is specified in
</
span
>
<
span
>
The compiler version is specified in
</
span
>
...
...
ui/contractVerification/fields/ContractVerificationFieldEvmVersion.tsx
View file @
7c00d780
import
{
Link
}
from
'
@chakra-ui/react
'
;
import
{
Link
}
from
'
@chakra-ui/react
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
type
{
ControllerRenderProps
}
from
'
react-hook-form
'
;
import
{
useFormContext
,
Controller
}
from
'
react-hook-form
'
;
import
{
useFormContext
,
Controller
}
from
'
react-hook-form
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
type
{
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
FancySelect
from
'
ui/shared/FancySelect/FancySelect
'
;
import
FancySelect
from
'
ui/shared/FancySelect/FancySelect
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
const
VERSIONS
=
[
interface
Props
{
'
default
'
,
isVyper
?:
boolean
;
'
london
'
,
}
'
berlin
'
,
];
const
ContractVerificationFieldEvmVersion
=
()
=>
{
const
ContractVerificationFieldEvmVersion
=
(
{
isVyper
}:
Props
)
=>
{
const
{
formState
,
control
}
=
useFormContext
<
FormFields
>
();
const
{
formState
,
control
}
=
useFormContext
<
FormFields
>
();
const
isMobile
=
useIsMobile
();
const
isMobile
=
useIsMobile
();
const
queryClient
=
useQueryClient
();
const
config
=
queryClient
.
getQueryData
<
SmartContractVerificationConfig
>
(
getResourceKey
(
'
contract_verification_config
'
));
const
options
=
React
.
useMemo
(()
=>
(
const
options
=
React
.
useMemo
(()
=>
(
VERSIONS
.
map
((
option
)
=>
({
label
:
option
,
value
:
option
}))
(
isVyper
?
config
?.
vyper_evm_versions
:
config
?.
solidity_evm_versions
)?.
map
((
option
)
=>
({
label
:
option
,
value
:
option
}))
||
[]
),
[
]);
),
[
config
?.
solidity_evm_versions
,
config
?.
vyper_evm_versions
,
isVyper
]);
const
renderControl
=
React
.
useCallback
(({
field
}:
{
field
:
ControllerRenderProps
<
FormFields
,
'
evm_version
'
>
})
=>
{
const
renderControl
=
React
.
useCallback
(({
field
}:
{
field
:
ControllerRenderProps
<
FormFields
,
'
evm_version
'
>
})
=>
{
const
error
=
'
evm_version
'
in
formState
.
errors
?
formState
.
errors
.
evm_version
:
undefined
;
const
error
=
'
evm_version
'
in
formState
.
errors
?
formState
.
errors
.
evm_version
:
undefined
;
...
...
ui/contractVerification/fields/ContractVerificationFieldMethod.tsx
View file @
7c00d780
...
@@ -20,30 +20,24 @@ import React from 'react';
...
@@ -20,30 +20,24 @@ import React from 'react';
import
type
{
ControllerRenderProps
,
Control
}
from
'
react-hook-form
'
;
import
type
{
ControllerRenderProps
,
Control
}
from
'
react-hook-form
'
;
import
{
Controller
}
from
'
react-hook-form
'
;
import
{
Controller
}
from
'
react-hook-form
'
;
import
type
{
FormFields
,
VerificationMethod
}
from
'
../types
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
type
{
SmartContractVerificationMethod
,
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
infoIcon
from
'
icons/info.svg
'
;
import
infoIcon
from
'
icons/info.svg
'
;
export
const
VERIFICATION_METHODS
:
Array
<
VerificationMethod
>
=
[
'
flatten_source_code
'
,
'
standard_input
'
,
'
sourcify
'
,
'
multi_part_file
'
,
'
vyper_contract
'
,
];
interface
Props
{
interface
Props
{
control
:
Control
<
FormFields
>
;
control
:
Control
<
FormFields
>
;
isDisabled
?:
boolean
;
isDisabled
?:
boolean
;
methods
:
SmartContractVerificationConfig
[
'
verification_options
'
];
}
}
const
ContractVerificationFieldMethod
=
({
control
,
isDisabled
}:
Props
)
=>
{
const
ContractVerificationFieldMethod
=
({
control
,
isDisabled
,
methods
}:
Props
)
=>
{
const
[
isPopoverOpen
,
setIsPopoverOpen
]
=
useBoolean
();
const
[
isPopoverOpen
,
setIsPopoverOpen
]
=
useBoolean
();
const
tooltipBg
=
useColorModeValue
(
'
gray.700
'
,
'
gray.900
'
);
const
tooltipBg
=
useColorModeValue
(
'
gray.700
'
,
'
gray.900
'
);
const
renderItem
=
React
.
useCallback
((
method
:
VerificationMethod
)
=>
{
const
renderItem
=
React
.
useCallback
((
method
:
SmartContract
VerificationMethod
)
=>
{
switch
(
method
)
{
switch
(
method
)
{
case
'
flatten
_source
_code
'
:
case
'
flatten
ed
_code
'
:
return
'
Via flattened source code
'
;
return
'
Via flattened source code
'
;
case
'
standard_input
'
:
case
'
standard_input
'
:
return
(
return
(
...
@@ -91,9 +85,9 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => {
...
@@ -91,9 +85,9 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => {
</
Popover
>
</
Popover
>
</>
</>
);
);
case
'
multi_part
_file
'
:
case
'
multi_part
'
:
return
'
Via multi-part files
'
;
return
'
Via multi-part files
'
;
case
'
vyper_
contrac
t
'
:
case
'
vyper_
multi_par
t
'
:
return
'
Vyper contract
'
;
return
'
Vyper contract
'
;
default
:
default
:
...
@@ -105,13 +99,13 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => {
...
@@ -105,13 +99,13 @@ const ContractVerificationFieldMethod = ({ control, isDisabled }: Props) => {
return
(
return
(
<
RadioGroup
defaultValue=
"add"
colorScheme=
"blue"
isDisabled=
{
isDisabled
}
{
...
field
}
>
<
RadioGroup
defaultValue=
"add"
colorScheme=
"blue"
isDisabled=
{
isDisabled
}
{
...
field
}
>
<
Stack
spacing=
{
4
}
>
<
Stack
spacing=
{
4
}
>
{
VERIFICATION_METHODS
.
map
((
method
)
=>
{
{
methods
.
map
((
method
)
=>
{
return
<
Radio
key=
{
method
}
value=
{
method
}
size=
"lg"
>
{
renderItem
(
method
)
}
</
Radio
>;
return
<
Radio
key=
{
method
}
value=
{
method
}
size=
"lg"
>
{
renderItem
(
method
)
}
</
Radio
>;
})
}
})
}
</
Stack
>
</
Stack
>
</
RadioGroup
>
</
RadioGroup
>
);
);
},
[
isDisabled
,
renderItem
]);
},
[
isDisabled
,
methods
,
renderItem
]);
return
(
return
(
<
section
>
<
section
>
...
...
ui/contractVerification/types.ts
View file @
7c00d780
import
type
{
Option
}
from
'
ui/shared/FancySelect/types
'
;
import
type
{
Option
}
from
'
ui/shared/FancySelect/types
'
;
export
type
VerificationMethod
=
'
flatten_source_code
'
|
'
standard_input
'
|
'
sourcify
'
|
'
multi_part_file
'
|
'
vyper_contract
'
export
interface
ContractLibrary
{
export
interface
ContractLibrary
{
name
:
string
;
name
:
string
;
address
:
string
;
address
:
string
;
}
}
export
interface
FormFieldsFlattenSourceCode
{
export
interface
FormFieldsFlattenSourceCode
{
method
:
'
flatten
_source
_code
'
;
method
:
'
flatten
ed
_code
'
;
is_yul
:
boolean
;
is_yul
:
boolean
;
name
:
string
;
name
:
string
;
compiler
:
Option
;
compiler
:
Option
;
...
@@ -32,7 +30,7 @@ export interface FormFieldsSourcify {
...
@@ -32,7 +30,7 @@ export interface FormFieldsSourcify {
}
}
export
interface
FormFieldsMultiPartFile
{
export
interface
FormFieldsMultiPartFile
{
method
:
'
multi_part
_file
'
;
method
:
'
multi_part
'
;
compiler
:
Option
;
compiler
:
Option
;
evm_version
:
Option
;
evm_version
:
Option
;
is_optimization_enabled
:
boolean
;
is_optimization_enabled
:
boolean
;
...
@@ -41,7 +39,7 @@ export interface FormFieldsMultiPartFile {
...
@@ -41,7 +39,7 @@ export interface FormFieldsMultiPartFile {
}
}
export
interface
FormFieldsVyperContract
{
export
interface
FormFieldsVyperContract
{
method
:
'
vyper_
contrac
t
'
;
method
:
'
vyper_
multi_par
t
'
;
name
:
string
;
name
:
string
;
compiler
:
Option
;
compiler
:
Option
;
code
:
string
;
code
:
string
;
...
...
ui/contractVerification/utils.ts
0 → 100644
View file @
7c00d780
import
type
{
SmartContractVerificationMethod
}
from
'
types/api/contract
'
;
export
const
SUPPORTED_VERIFICATION_METHODS
:
Array
<
SmartContractVerificationMethod
>
=
[
'
flattened_code
'
,
'
standard_input
'
,
'
sourcify
'
,
'
multi_part
'
,
'
vyper_multi_part
'
,
];
export
function
isValidVerificationMethod
(
method
?:
string
):
method
is
SmartContractVerificationMethod
{
return
method
&&
SUPPORTED_VERIFICATION_METHODS
.
includes
(
method
as
SmartContractVerificationMethod
)
?
true
:
false
;
}
ui/pages/ContractVerification.tsx
View file @
7c00d780
...
@@ -2,13 +2,19 @@ import { Text } from '@chakra-ui/react';
...
@@ -2,13 +2,19 @@ import { Text } from '@chakra-ui/react';
import
{
useRouter
}
from
'
next/router
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
SmartContractVerificationConfigRaw
,
SmartContractVerificationMethod
}
from
'
types/api/contract
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
useAppContext
}
from
'
lib/appContext
'
;
import
{
useAppContext
}
from
'
lib/appContext
'
;
import
isBrowser
from
'
lib/isBrowser
'
;
import
isBrowser
from
'
lib/isBrowser
'
;
import
link
from
'
lib/link/link
'
;
import
link
from
'
lib/link/link
'
;
import
ContractVerificationForm
from
'
ui/contractVerification/ContractVerificationForm
'
;
import
ContractVerificationForm
from
'
ui/contractVerification/ContractVerificationForm
'
;
import
{
isValidVerificationMethod
}
from
'
ui/contractVerification/utils
'
;
import
Address
from
'
ui/shared/address/Address
'
;
import
Address
from
'
ui/shared/address/Address
'
;
import
AddressIcon
from
'
ui/shared/address/AddressIcon
'
;
import
AddressIcon
from
'
ui/shared/address/AddressIcon
'
;
import
ContentLoader
from
'
ui/shared/ContentLoader
'
;
import
CopyToClipboard
from
'
ui/shared/CopyToClipboard
'
;
import
CopyToClipboard
from
'
ui/shared/CopyToClipboard
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
Page
from
'
ui/shared/Page/Page
'
;
import
Page
from
'
ui/shared/Page/Page
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
...
@@ -21,7 +27,20 @@ const ContractVerification = () => {
...
@@ -21,7 +27,20 @@ const ContractVerification = () => {
const
router
=
useRouter
();
const
router
=
useRouter
();
const
hash
=
router
.
query
.
id
?.
toString
();
const
hash
=
router
.
query
.
id
?.
toString
();
const
method
=
router
.
query
.
id
?.
toString
();
const
method
=
router
.
query
.
id
?.
toString
()
as
SmartContractVerificationMethod
|
undefined
;
const
configQuery
=
useApiQuery
(
'
contract_verification_config
'
,
{
queryOptions
:
{
select
:
(
data
:
unknown
)
=>
{
const
_data
=
data
as
SmartContractVerificationConfigRaw
;
return
{
...
_data
,
verification_options
:
_data
.
verification_options
.
filter
(
isValidVerificationMethod
),
};
},
enabled
:
Boolean
(
hash
),
},
});
React
.
useEffect
(()
=>
{
React
.
useEffect
(()
=>
{
if
(
method
&&
hash
)
{
if
(
method
&&
hash
)
{
...
@@ -31,6 +50,23 @@ const ContractVerification = () => {
...
@@ -31,6 +50,23 @@ const ContractVerification = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
]);
},
[
]);
const
content
=
(()
=>
{
if
(
configQuery
.
isError
)
{
return
<
DataFetchAlert
/>;
}
if
(
configQuery
.
isLoading
)
{
return
<
ContentLoader
/>;
}
return
(
<
ContractVerificationForm
method=
{
method
&&
configQuery
.
data
.
verification_options
.
includes
(
method
)
?
method
:
undefined
}
config=
{
configQuery
.
data
}
/>
);
})();
return
(
return
(
<
Page
>
<
Page
>
<
PageTitle
<
PageTitle
...
@@ -39,7 +75,7 @@ const ContractVerification = () => {
...
@@ -39,7 +75,7 @@ const ContractVerification = () => {
backLinkLabel=
"Back to contract"
backLinkLabel=
"Back to contract"
/>
/>
{
hash
&&
(
{
hash
&&
(
<
Address
>
<
Address
mb=
{
12
}
>
<
AddressIcon
address=
{
{
hash
,
is_contract
:
true
,
implementation_name
:
null
}
}
flexShrink=
{
0
}
/>
<
AddressIcon
address=
{
{
hash
,
is_contract
:
true
,
implementation_name
:
null
}
}
flexShrink=
{
0
}
/>
<
Text
fontFamily=
"heading"
ml=
{
2
}
fontWeight=
{
500
}
fontSize=
"lg"
w=
{
{
base
:
'
100%
'
,
lg
:
'
auto
'
}
}
whiteSpace=
"nowrap"
overflow=
"hidden"
>
<
Text
fontFamily=
"heading"
ml=
{
2
}
fontWeight=
{
500
}
fontSize=
"lg"
w=
{
{
base
:
'
100%
'
,
lg
:
'
auto
'
}
}
whiteSpace=
"nowrap"
overflow=
"hidden"
>
<
HashStringShortenDynamic
hash=
{
hash
}
/>
<
HashStringShortenDynamic
hash=
{
hash
}
/>
...
@@ -47,7 +83,7 @@ const ContractVerification = () => {
...
@@ -47,7 +83,7 @@ const ContractVerification = () => {
<
CopyToClipboard
text=
{
hash
}
/>
<
CopyToClipboard
text=
{
hash
}
/>
</
Address
>
</
Address
>
)
}
)
}
<
ContractVerificationForm
/>
{
content
}
</
Page
>
</
Page
>
);
);
};
};
...
...
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