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
532f7e7a
Commit
532f7e7a
authored
Mar 06, 2025
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
contract verification: flattened code method
parent
cdb1793c
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
318 additions
and
284 deletions
+318
-284
eslint.config.mjs
eslint.config.mjs
+1
-0
contract-verification.tsx
pages/address/[hash]/contract-verification.tsx
+2
-2
contract-verification.tsx
pages/contract-verification.tsx
+2
-2
index.ts
toolkit/theme/recipes/index.ts
+2
-0
input.recipe.ts
toolkit/theme/recipes/input.recipe.ts
+3
-0
list.recipe.ts
toolkit/theme/recipes/list.recipe.ts
+67
-0
ContractVerificationForm.tsx
ui/contractVerification/ContractVerificationForm.tsx
+32
-43
ContractVerificationFieldAddress.tsx
...tVerification/fields/ContractVerificationFieldAddress.tsx
+4
-5
ContractVerificationFieldCode.tsx
...ractVerification/fields/ContractVerificationFieldCode.tsx
+1
-2
ContractVerificationFieldCompiler.tsx
...Verification/fields/ContractVerificationFieldCompiler.tsx
+31
-21
ContractVerificationFieldConstructorArgs.tsx
...ation/fields/ContractVerificationFieldConstructorArgs.tsx
+2
-3
ContractVerificationFieldEvmVersion.tsx
...rification/fields/ContractVerificationFieldEvmVersion.tsx
+11
-8
ContractVerificationFieldLibraries.tsx
...erification/fields/ContractVerificationFieldLibraries.tsx
+4
-3
ContractVerificationFieldLibraryItem.tsx
...ification/fields/ContractVerificationFieldLibraryItem.tsx
+14
-13
ContractVerificationFieldLicenseType.tsx
...ification/fields/ContractVerificationFieldLicenseType.tsx
+7
-4
ContractVerificationFieldMethod.tsx
...ctVerification/fields/ContractVerificationFieldMethod.tsx
+41
-57
ContractVerificationFieldName.tsx
...ractVerification/fields/ContractVerificationFieldName.tsx
+1
-2
ContractVerificationFieldOptimization.tsx
...fication/fields/ContractVerificationFieldOptimization.tsx
+5
-3
types.ts
ui/contractVerification/types.ts
+15
-20
utils.ts
ui/contractVerification/utils.ts
+58
-91
ContractVerificationForAddress.tsx
ui/pages/ContractVerificationForAddress.tsx
+2
-0
VerifiedAddresses.tsx
ui/pages/VerifiedAddresses.tsx
+2
-2
FormFieldText.tsx
ui/shared/forms/fields/FormFieldText.tsx
+11
-3
No files found.
eslint.config.mjs
View file @
532f7e7a
...
...
@@ -29,6 +29,7 @@ const RESTRICTED_MODULES = {
{
name
:
'
ui/shared/Tabs/RoutedTabs
'
,
message
:
'
Please use RoutedTabs component from toolkit/components/RoutedTabs instead
'
},
{
name
:
'
ui/shared/chakra/Tag
'
,
message
:
'
Please use Tag component from toolkit/chakra instead
'
},
{
name
:
'
ui/shared/select/Select
'
,
message
:
'
Please use Select component from toolkit/chakra instead
'
},
{
name
:
'
ui/shared/forms/fields/FormFieldFancySelect
'
,
message
:
'
Please use FormFieldSelect component
'
},
{
name
:
'
@chakra-ui/react
'
,
importNames
:
[
...
...
pages/address/[hash]/contract-verification.tsx
View file @
532f7e7a
...
...
@@ -4,12 +4,12 @@ import React from 'react';
import
type
{
Props
}
from
'
nextjs/getServerSideProps
'
;
import
PageNextJs
from
'
nextjs/PageNextJs
'
;
//
import ContractVerificationForAddress from 'ui/pages/ContractVerificationForAddress';
import
ContractVerificationForAddress
from
'
ui/pages/ContractVerificationForAddress
'
;
const
Page
:
NextPage
<
Props
>
=
(
props
:
Props
)
=>
{
return
(
<
PageNextJs
pathname=
"/address/[hash]/contract-verification"
query=
{
props
.
query
}
>
{
/* <ContractVerificationForAddress/> */
}
<
ContractVerificationForAddress
/>
</
PageNextJs
>
);
};
...
...
pages/contract-verification.tsx
View file @
532f7e7a
...
...
@@ -4,12 +4,12 @@ import React from 'react';
import
type
{
Props
}
from
'
nextjs/getServerSideProps
'
;
import
PageNextJs
from
'
nextjs/PageNextJs
'
;
//
import ContractVerification from 'ui/pages/ContractVerification';
import
ContractVerification
from
'
ui/pages/ContractVerification
'
;
const
Page
:
NextPage
<
Props
>
=
(
props
:
Props
)
=>
{
return
(
<
PageNextJs
pathname=
"/contract-verification"
query=
{
props
.
query
}
>
{
/* <ContractVerification/> */
}
<
ContractVerification
/>
</
PageNextJs
>
);
};
...
...
toolkit/theme/recipes/index.ts
View file @
532f7e7a
...
...
@@ -10,6 +10,7 @@ import { recipe as drawer } from './drawer.recipe';
import
{
recipe
as
field
}
from
'
./field.recipe
'
;
import
{
recipe
as
input
}
from
'
./input.recipe
'
;
import
{
recipe
as
link
}
from
'
./link.recipe
'
;
import
{
recipe
as
list
}
from
'
./list.recipe
'
;
import
{
recipe
as
menu
}
from
'
./menu.recipe
'
;
import
{
recipe
as
nativeSelect
}
from
'
./native-select.recipe
'
;
import
{
recipe
as
pinInput
}
from
'
./pin-input.recipe
'
;
...
...
@@ -49,6 +50,7 @@ export const slotRecipes = {
dialog
,
drawer
,
field
,
list
,
menu
,
nativeSelect
,
pinInput
,
...
...
toolkit/theme/recipes/input.recipe.ts
View file @
532f7e7a
...
...
@@ -64,6 +64,9 @@ export const recipe = defineRecipe({
},
_placeholderShown
:
{
borderColor
:
'
input.border
'
,
_invalid
:
{
borderColor
:
'
input.border.error
'
,
},
},
_hover
:
{
borderColor
:
'
input.border.hover
'
,
...
...
toolkit/theme/recipes/list.recipe.ts
0 → 100644
View file @
532f7e7a
import
{
defineSlotRecipe
}
from
'
@chakra-ui/react
'
;
export
const
recipe
=
defineSlotRecipe
({
slots
:
[
'
root
'
,
'
item
'
,
'
indicator
'
],
base
:
{
root
:
{
display
:
'
flex
'
,
flexDirection
:
'
column
'
,
gap
:
'
var(--list-gap)
'
,
'
& :where(ul, ol)
'
:
{
marginTop
:
'
var(--list-gap)
'
,
},
},
item
:
{
whiteSpace
:
'
normal
'
,
display
:
'
list-item
'
,
'
&::marker
'
:
{
color
:
'
inherit
'
,
},
},
indicator
:
{
marginEnd
:
'
2
'
,
minHeight
:
'
1lh
'
,
flexShrink
:
0
,
display
:
'
inline-block
'
,
verticalAlign
:
'
middle
'
,
},
},
variants
:
{
variant
:
{
marker
:
{
root
:
{
listStyle
:
'
revert
'
,
},
item
:
{
_marker
:
{
color
:
'
inherit
'
,
},
},
},
plain
:
{
item
:
{
alignItems
:
'
flex-start
'
,
display
:
'
inline-flex
'
,
},
},
},
align
:
{
center
:
{
item
:
{
alignItems
:
'
center
'
},
},
start
:
{
item
:
{
alignItems
:
'
flex-start
'
},
},
end
:
{
item
:
{
alignItems
:
'
flex-end
'
},
},
},
},
defaultVariants
:
{
variant
:
'
marker
'
,
},
});
ui/contractVerification/ContractVerificationForm.tsx
View file @
532f7e7a
import
{
Button
,
Grid
,
Text
,
chakra
,
useUpdateEffect
}
from
'
@chakra-ui/react
'
;
import
{
Grid
,
Text
,
chakra
,
useUpdateEffect
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
SubmitHandler
}
from
'
react-hook-form
'
;
import
{
useForm
,
FormProvider
}
from
'
react-hook-form
'
;
...
...
@@ -14,24 +14,25 @@ import useApiFetch from 'lib/api/useApiFetch';
import
capitalizeFirstLetter
from
'
lib/capitalizeFirstLetter
'
;
import
delay
from
'
lib/delay
'
;
import
getErrorObjStatusCode
from
'
lib/errors/getErrorObjStatusCode
'
;
import
useToast
from
'
lib/hooks/useToast
'
;
import
*
as
mixpanel
from
'
lib/mixpanel/index
'
;
import
useSocketChannel
from
'
lib/socket/useSocketChannel
'
;
import
useSocketMessage
from
'
lib/socket/useSocketMessage
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
toaster
}
from
'
toolkit/chakra/toaster
'
;
import
ContractVerificationFieldAddress
from
'
./fields/ContractVerificationFieldAddress
'
;
import
ContractVerificationFieldLicenseType
from
'
./fields/ContractVerificationFieldLicenseType
'
;
import
ContractVerificationFieldMethod
from
'
./fields/ContractVerificationFieldMethod
'
;
import
ContractVerificationFlattenSourceCode
from
'
./methods/ContractVerificationFlattenSourceCode
'
;
import
ContractVerificationMultiPartFile
from
'
./methods/ContractVerificationMultiPartFile
'
;
import
ContractVerificationSolidityFoundry
from
'
./methods/ContractVerificationSolidityFoundry
'
;
import
ContractVerificationSolidityHardhat
from
'
./methods/ContractVerificationSolidityHardhat
'
;
import
ContractVerificationSourcify
from
'
./methods/ContractVerificationSourcify
'
;
import
ContractVerificationStandardInput
from
'
./methods/ContractVerificationStandardInput
'
;
import
ContractVerificationStylusGitHubRepo
from
'
./methods/ContractVerificationStylusGitHubRepo
'
;
import
ContractVerificationVyperContract
from
'
./methods/ContractVerificationVyperContract
'
;
import
ContractVerificationVyperMultiPartFile
from
'
./methods/ContractVerificationVyperMultiPartFile
'
;
import
ContractVerificationVyperStandardInput
from
'
./methods/ContractVerificationVyperStandardInput
'
;
//
import ContractVerificationMultiPartFile from './methods/ContractVerificationMultiPartFile';
//
import ContractVerificationSolidityFoundry from './methods/ContractVerificationSolidityFoundry';
//
import ContractVerificationSolidityHardhat from './methods/ContractVerificationSolidityHardhat';
//
import ContractVerificationSourcify from './methods/ContractVerificationSourcify';
//
import ContractVerificationStandardInput from './methods/ContractVerificationStandardInput';
//
import ContractVerificationStylusGitHubRepo from './methods/ContractVerificationStylusGitHubRepo';
//
import ContractVerificationVyperContract from './methods/ContractVerificationVyperContract';
//
import ContractVerificationVyperMultiPartFile from './methods/ContractVerificationVyperMultiPartFile';
//
import ContractVerificationVyperStandardInput from './methods/ContractVerificationVyperStandardInput';
import
{
prepareRequestBody
,
formatSocketErrors
,
getDefaultValues
,
METHOD_LABELS
}
from
'
./utils
'
;
interface
Props
{
...
...
@@ -43,14 +44,13 @@ interface Props {
const
ContractVerificationForm
=
({
method
:
methodFromQuery
,
config
,
hash
}:
Props
)
=>
{
const
formApi
=
useForm
<
FormFields
>
({
mode
:
'
onBlur
'
,
defaultValues
:
getDefaultValues
(
methodFromQuery
,
config
,
hash
,
null
),
defaultValues
:
getDefaultValues
(
methodFromQuery
,
config
,
hash
,
[]
),
});
const
{
handleSubmit
,
watch
,
formState
,
setError
,
reset
,
getFieldState
,
getValues
,
clearErrors
}
=
formApi
;
const
submitPromiseResolver
=
React
.
useRef
<
(
value
:
unknown
)
=>
void
>
();
const
methodNameRef
=
React
.
useRef
<
string
>
();
const
apiFetch
=
useApiFetch
();
const
toast
=
useToast
();
const
onFormSubmit
:
SubmitHandler
<
FormFields
>
=
React
.
useCallback
(
async
(
data
)
=>
{
const
body
=
prepareRequestBody
(
data
);
...
...
@@ -76,7 +76,7 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
try
{
await
apiFetch
(
'
contract_verification_via
'
,
{
pathParams
:
{
method
:
data
.
method
.
value
,
hash
:
data
.
address
.
toLowerCase
()
},
pathParams
:
{
method
:
data
.
method
[
0
]
,
hash
:
data
.
address
.
toLowerCase
()
},
fetchParams
:
{
method
:
'
POST
'
,
body
,
...
...
@@ -116,13 +116,9 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
return
;
}
toast
({
position
:
'
top-right
'
,
toaster
.
success
({
title
:
'
Success
'
,
description
:
'
Contract is successfully verified.
'
,
status
:
'
success
'
,
variant
:
'
subtle
'
,
isClosable
:
true
,
});
mixpanel
.
logEvent
(
...
...
@@ -132,7 +128,7 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
);
window
.
location
.
assign
(
route
({
pathname
:
'
/address/[hash]
'
,
query
:
{
hash
:
address
,
tab
:
'
contract
'
}
}));
},
[
setError
,
toast
,
address
,
getValues
]);
},
[
setError
,
address
,
getValues
]);
const
handleSocketError
=
React
.
useCallback
(()
=>
{
if
(
!
formState
.
isSubmitting
)
{
...
...
@@ -141,20 +137,14 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
submitPromiseResolver
.
current
?.(
null
);
const
toastId
=
'
socket-error
'
;
!
toast
.
isActive
(
toastId
)
&&
toast
({
id
:
toastId
,
position
:
'
top-right
'
,
toaster
.
error
({
title
:
'
Error
'
,
description
:
'
There was an error with socket connection. Try again later.
'
,
status
:
'
error
'
,
variant
:
'
subtle
'
,
isClosable
:
true
,
});
// callback should not change when form is submitted
// otherwise it will resubscribe to channel, but we don't want that since in that case we might miss verification result message
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
toast
]);
},
[
]);
const
channel
=
useSocketChannel
({
topic
:
`addresses:
${
address
?.
toLowerCase
()
}
`,
...
...
@@ -171,21 +161,21 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
const methods = React.useMemo(() => {
return {
'flattened-code': <ContractVerificationFlattenSourceCode config={ config }/>,
'standard-input': <ContractVerificationStandardInput config={ config }/>,
sourcify: <ContractVerificationSourcify/>,
'multi-part': <ContractVerificationMultiPartFile/>,
'vyper-code': <ContractVerificationVyperContract config={ config }/>,
'vyper-multi-part': <ContractVerificationVyperMultiPartFile/>,
'vyper-standard-input': <ContractVerificationVyperStandardInput/>,
'solidity-hardhat': <ContractVerificationSolidityHardhat config={ config }/>,
'solidity-foundry': <ContractVerificationSolidityFoundry/>,
'stylus-github-repository': <ContractVerificationStylusGitHubRepo/>,
//
'standard-input': <ContractVerificationStandardInput config={ config }/>,
//
sourcify: <ContractVerificationSourcify/>,
//
'multi-part': <ContractVerificationMultiPartFile/>,
//
'vyper-code': <ContractVerificationVyperContract config={ config }/>,
//
'vyper-multi-part': <ContractVerificationVyperMultiPartFile/>,
//
'vyper-standard-input': <ContractVerificationVyperStandardInput/>,
//
'solidity-hardhat': <ContractVerificationSolidityHardhat config={ config }/>,
//
'solidity-foundry': <ContractVerificationSolidityFoundry/>,
//
'stylus-github-repository': <ContractVerificationStylusGitHubRepo/>,
};
}, [ config ]);
const method = watch('method');
const methodValue = method?.[0];
const licenseType = watch('license_type');
const content = methods[method?.value] || null;
const methodValue = method?.value;
const content = methods[methodValue] || null;
useUpdateEffect(() => {
if (methodValue) {
...
...
@@ -212,13 +202,12 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
</Grid>
{ content }
{ formState.errors.root?.message && <Text color="error"mt={ 4 } fontSize="sm" whiteSpace="pre-wrap">{ formState.errors.root.message }</Text> }
{ Boolean(method) && method
.value !== 'solidity-hardhat' && method.v
alue !== 'solidity-foundry' && (
{ Boolean(method) && method
Value !== 'solidity-hardhat' && methodV
alue !== 'solidity-foundry' && (
<Button
variant="solid"
size="lg"
size="md"
type="submit"
mt={ 12 }
isL
oading={ formState.isSubmitting }
l
oading={ formState.isSubmitting }
loadingText="Verify & publish"
>
Verify & publish
...
...
ui/contractVerification/fields/ContractVerificationFieldAddress.tsx
View file @
532f7e7a
...
...
@@ -8,10 +8,10 @@ import FormFieldAddress from 'ui/shared/forms/fields/FormFieldAddress';
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
interface
Props
{
isR
eadOnly
?:
boolean
;
r
eadOnly
?:
boolean
;
}
const
ContractVerificationFieldAddress
=
({
isR
eadOnly
}:
Props
)
=>
{
const
ContractVerificationFieldAddress
=
({
r
eadOnly
}:
Props
)
=>
{
return
(
<>
<
ContractVerificationFormRow
>
...
...
@@ -22,10 +22,9 @@ const ContractVerificationFieldAddress = ({ isReadOnly }: Props) => {
<
ContractVerificationFormRow
>
<
FormFieldAddress
<
FormFields
>
name="address"
isR
equired
r
equired
placeholder="Smart contract / Address (0x...)"
isReadOnly=
{
isReadOnly
}
size=
{
{
base
:
'
md
'
,
lg
:
'
lg
'
}
}
readOnly=
{
readOnly
}
/
>
</
ContractVerificationFormRow
>
</>
...
...
ui/contractVerification/fields/ContractVerificationFieldCode.tsx
View file @
532f7e7a
...
...
@@ -15,9 +15,8 @@ const ContractVerificationFieldCode = ({ isVyper }: Props) => {
<
ContractVerificationFormRow
>
<
FormFieldText
<
FormFields
>
name="code"
isR
equired
r
equired
placeholder="Contract code"
size=
{
{
base
:
'
md
'
,
lg
:
'
lg
'
}
}
asComponent="Textarea"
/
>
{
isVyper
?
null
:
(
...
...
ui/contractVerification/fields/ContractVerificationFieldCompiler.tsx
View file @
532f7e7a
import
{
chakra
,
C
heckbox
,
Code
}
from
'
@chakra-ui/react
'
;
import
{
chakra
,
C
ode
,
createListCollection
}
from
'
@chakra-ui/react
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
{
useFormContext
}
from
'
react-hook-form
'
;
...
...
@@ -7,8 +7,8 @@ import type { FormFields } from '../types';
import
type
{
SmartContractVerificationConfig
}
from
'
types/client/contract
'
;
import
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
FormFieldFancySelect
from
'
ui/shared/forms/fields/FormFieldFancySelect
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
Checkbox
}
from
'
toolkit/chakra/checkbox
'
;
import
FormFieldSelect
from
'
ui/shared/forms/fields/FormFieldSelect
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
...
...
@@ -26,12 +26,15 @@ const ContractVerificationFieldCompiler = ({ isVyper, isStylus }: Props) => {
const
config
=
queryClient
.
getQueryData
<
SmartContractVerificationConfig
>
(
getResourceKey
(
'
contract_verification_config
'
));
const
handleCheckboxChange
=
React
.
useCallback
(()
=>
{
if
(
isNightly
)
{
const
field
=
getValues
(
'
compiler
'
);
field
?.
value
.
includes
(
'
nightly
'
)
&&
resetField
(
'
compiler
'
,
{
defaultValue
:
null
});
}
setIsNightly
(
prev
=>
!
prev
);
},
[
getValues
,
isNightly
,
resetField
]);
setIsNightly
(
prev
=>
{
if
(
prev
)
{
const
field
=
getValues
(
'
compiler
'
);
field
?.[
0
]?.
includes
(
'
nightly
'
)
&&
resetField
(
'
compiler
'
,
{
defaultValue
:
[]
});
}
return
!
prev
;
});
},
[
getValues
,
resetField
]);
const
options
=
React
.
useMemo
(()
=>
{
const
versions
=
(()
=>
{
...
...
@@ -47,11 +50,21 @@ const ContractVerificationFieldCompiler = ({ isVyper, isStylus }: Props) => {
return
versions
?.
map
((
option
)
=>
({
label
:
option
,
value
:
option
}))
||
[];
},
[
isStylus
,
isVyper
,
config
?.
solidity_compiler_versions
,
config
?.
stylus_compiler_versions
,
config
?.
vyper_compiler_versions
]);
const
loadOptions
=
React
.
useCallback
(
async
(
inputValue
:
string
)
=>
{
return
options
.
filter
(({
label
})
=>
!
inputValue
||
label
.
toLowerCase
().
includes
(
inputValue
.
toLowerCase
()))
// const loadOptions = React.useCallback(async(inputValue: string) => {
// return options
// .filter(({ label }) => !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()))
// .filter(({ label }) => isNightly ? true : !label.includes('nightly'))
// .slice(0, OPTIONS_LIMIT);
// }, [ isNightly, options ]);
// TODO @tom2drum implement filtering the options
const
collection
=
React
.
useMemo
(()
=>
{
const
items
=
options
// .filter(({ label }) => !inputValue || label.toLowerCase().includes(inputValue.toLowerCase()))
.
filter
(({
label
})
=>
isNightly
?
true
:
!
label
.
includes
(
'
nightly
'
))
.
slice
(
0
,
OPTIONS_LIMIT
);
return
createListCollection
({
items
});
},
[
isNightly
,
options
]);
return
(
...
...
@@ -59,22 +72,19 @@ const ContractVerificationFieldCompiler = ({ isVyper, isStylus }: Props) => {
<>
{
!
isVyper
&&
!
isStylus
&&
(
<
Checkbox
size=
"lg"
mb=
{
2
}
onChange=
{
handleCheckboxChange
}
isDisabled=
{
formState
.
isSubmitting
}
checked=
{
isNightly
}
onCheckedChange=
{
handleCheckboxChange
}
disabled=
{
formState
.
isSubmitting
}
>
Include nightly builds
</
Checkbox
>
)
}
<
FormField
Fancy
Select
<
FormFields
,
'
compiler
'
>
<
FormFieldSelect
<
FormFields
,
'
compiler
'
>
name="compiler"
placeholder="Compiler (enter version or use the dropdown)"
loadOptions=
{
loadOptions
}
defaultOptions
placeholderIcon=
{
<
IconSvg
name=
"search"
/>
}
isRequired
isAsync
collection=
{
collection
}
required
/
>
</>
{
isVyper
||
isStylus
?
null
:
(
...
...
ui/contractVerification/fields/ContractVerificationFieldConstructorArgs.tsx
View file @
532f7e7a
import
{
Link
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
FormFieldText
from
'
ui/shared/forms/fields/FormFieldText
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
...
...
@@ -12,10 +12,9 @@ const ContractVerificationFieldConstructorArgs = () => {
<
ContractVerificationFormRow
>
<
FormFieldText
<
FormFields
>
name="constructor_args"
isR
equired
r
equired
rules=
{
{
maxLength
:
255
}
}
placeholder="ABI-encoded Constructor Arguments"
size=
{
{
base
:
'
md
'
,
lg
:
'
lg
'
}
}
asComponent="Textarea"
/
>
<>
...
...
ui/contractVerification/fields/ContractVerificationFieldEvmVersion.tsx
View file @
532f7e7a
import
{
Link
}
from
'
@chakra-ui/react
'
;
import
{
createListCollection
}
from
'
@chakra-ui/react
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
...
...
@@ -6,7 +6,8 @@ import type { FormFields } from '../types';
import
type
{
SmartContractVerificationConfig
}
from
'
types/client/contract
'
;
import
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
FormFieldFancySelect
from
'
ui/shared/forms/fields/FormFieldFancySelect
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
FormFieldSelect
from
'
ui/shared/forms/fields/FormFieldSelect
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
...
...
@@ -18,17 +19,19 @@ const ContractVerificationFieldEvmVersion = ({ isVyper }: Props) => {
const
queryClient
=
useQueryClient
();
const
config
=
queryClient
.
getQueryData
<
SmartContractVerificationConfig
>
(
getResourceKey
(
'
contract_verification_config
'
));
const
options
=
React
.
useMemo
(()
=>
(
(
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
collection
=
React
.
useMemo
(()
=>
{
const
items
=
(
isVyper
?
config
?.
vyper_evm_versions
:
config
?.
solidity_evm_versions
)?.
map
((
option
)
=>
({
label
:
option
,
value
:
option
}))
||
[];
return
createListCollection
({
items
});
},
[
config
?.
solidity_evm_versions
,
config
?.
vyper_evm_versions
,
isVyper
]);
return
(
<
ContractVerificationFormRow
>
<
FormField
Fancy
Select
<
FormFields
,
'
evm_version
'
>
<
FormFieldSelect
<
FormFields
,
'
evm_version
'
>
name="evm_version"
placeholder="EVM Version"
options=
{
options
}
isR
equired
collection=
{
collection
}
r
equired
/
>
<>
<
span
>
The EVM version the contract is written for. If the bytecode does not match the version, we try to verify using the latest EVM version.
</
span
>
...
...
ui/contractVerification/fields/ContractVerificationFieldLibraries.tsx
View file @
532f7e7a
import
{
Checkbox
,
useUpdateEffect
}
from
'
@chakra-ui/react
'
;
import
{
useUpdateEffect
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
useFieldArray
,
useFormContext
}
from
'
react-hook-form
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
{
Checkbox
}
from
'
toolkit/chakra/checkbox
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
import
ContractVerificationFieldLibraryItem
from
'
./ContractVerificationFieldLibraryItem
'
;
...
...
@@ -44,10 +46,9 @@ const ContractVerificationFieldLibraries = () => {
<>
<
ContractVerificationFormRow
>
<
Checkbox
size=
"lg"
onChange=
{
handleCheckboxChange
}
mt=
{
9
}
isD
isabled=
{
formState
.
isSubmitting
}
d
isabled=
{
formState
.
isSubmitting
}
>
Add contract libraries
</
Checkbox
>
...
...
ui/contractVerification/fields/ContractVerificationFieldLibraryItem.tsx
View file @
532f7e7a
import
{
Flex
,
IconButton
,
Text
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
Text
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
{
IconButton
}
from
'
toolkit/chakra/icon-button
'
;
import
FormFieldAddress
from
'
ui/shared/forms/fields/FormFieldAddress
'
;
import
FormFieldText
from
'
ui/shared/forms/fields/FormFieldText
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
...
...
@@ -38,7 +39,7 @@ const ContractVerificationFieldLibraryItem = ({ index, fieldsLength, onAddFieldC
<>
<
ContractVerificationFormRow
>
<
Flex
alignItems=
"center"
justifyContent=
"space-between"
ref=
{
ref
}
mt=
{
index
!==
0
?
6
:
0
}
>
<
Text
variant=
"
secondary"
fontSize=
"sm"
>
Contract library
{
index
+
1
}
</
Text
>
<
Text
color=
"text.
secondary"
fontSize=
"sm"
>
Contract library
{
index
+
1
}
</
Text
>
<
Flex
columnGap=
{
5
}
>
{
fieldsLength
>
1
&&
(
<
IconButton
...
...
@@ -47,9 +48,10 @@ const ContractVerificationFieldLibraryItem = ({ index, fieldsLength, onAddFieldC
w=
"30px"
h=
"30px"
onClick=
{
handleRemoveButtonClick
}
icon=
{
<
IconSvg
name=
"minus"
w=
"20px"
h=
"20px"
/>
}
isDisabled=
{
isDisabled
}
/>
disabled=
{
isDisabled
}
>
<
IconSvg
name=
"minus"
w=
"20px"
h=
"20px"
/>
</
IconButton
>
)
}
{
fieldsLength
<
LIMIT
&&
(
<
IconButton
...
...
@@ -58,9 +60,10 @@ const ContractVerificationFieldLibraryItem = ({ index, fieldsLength, onAddFieldC
w=
"30px"
h=
"30px"
onClick=
{
handleAddButtonClick
}
icon=
{
<
IconSvg
name=
"plus"
w=
"20px"
h=
"20px"
/>
}
isDisabled=
{
isDisabled
}
/>
disabled=
{
isDisabled
}
>
<
IconSvg
name=
"plus"
w=
"20px"
h=
"20px"
/>
</
IconButton
>
)
}
</
Flex
>
</
Flex
>
...
...
@@ -68,10 +71,9 @@ const ContractVerificationFieldLibraryItem = ({ index, fieldsLength, onAddFieldC
<
ContractVerificationFormRow
>
<
FormFieldText
<
FormFields
,
`
libraries
.
$
{
number
}
.
name
`
>
name=
{
`libraries.${ index }.name`
}
isR
equired
r
equired
rules=
{
{
maxLength
:
255
}
}
placeholder="Library name (.sol file)"
size=
{
{
base
:
'
md
'
,
lg
:
'
lg
'
}
}
/
>
{
index
===
0
?
(
<>
...
...
@@ -80,11 +82,10 @@ const ContractVerificationFieldLibraryItem = ({ index, fieldsLength, onAddFieldC
)
:
null
}
</
ContractVerificationFormRow
>
<
ContractVerificationFormRow
>
<
FormFieldAddress
<
FormFields
,
`
libraries
.
$
{
number
}
.
address
`
>
<
FormFieldAddress
<
FormFields
>
name=
{
`libraries.${ index }.address`
}
isR
equired
r
equired
placeholder="Library address (0x...)"
size=
{
{
base
:
'
md
'
,
lg
:
'
lg
'
}
}
/
>
{
index
===
0
?
(
<>
...
...
ui/contractVerification/fields/ContractVerificationFieldLicenseType.tsx
View file @
532f7e7a
import
{
createListCollection
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
{
CONTRACT_LICENSES
}
from
'
lib/contracts/licenses
'
;
import
FormField
FancySelect
from
'
ui/shared/forms/fields/FormFieldFancy
Select
'
;
import
FormField
Select
from
'
ui/shared/forms/fields/FormField
Select
'
;
import
ContractVerificationFormRow
from
'
../ContractVerificationFormRow
'
;
const
options
=
CONTRACT_LICENSES
.
map
(({
label
,
title
,
type
})
=>
({
label
:
`
${
title
}
(
${
label
}
)`
,
value
:
type
}));
const
collection
=
createListCollection
({
items
:
CONTRACT_LICENSES
.
map
(({
label
,
title
,
type
})
=>
({
label
:
`
${
title
}
(
${
label
}
)`
,
value
:
type
})),
});
const
ContractVerificationFieldLicenseType
=
()
=>
{
return
(
<
ContractVerificationFormRow
>
<
FormField
Fancy
Select
<
FormFields
,
'
license_type
'
>
<
FormFieldSelect
<
FormFields
,
'
license_type
'
>
name="license_type"
placeholder="Contract license"
options=
{
options
}
collection=
{
collection
}
/
>
<
span
>
For best practices, all contract source code holders, publishers and authors are encouraged to also
...
...
ui/contractVerification/fields/ContractVerificationFieldMethod.tsx
View file @
532f7e7a
import
{
Link
,
chakra
,
PopoverTrigger
,
Portal
,
PopoverContent
,
PopoverArrow
,
PopoverBody
,
useColorModeValue
,
DarkMode
,
ListItem
,
OrderedList
,
List
,
Box
,
createListCollection
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
FormFields
}
from
'
../types
'
;
import
type
{
SmartContractVerificationMethod
,
SmartContractVerificationConfig
}
from
'
types/client/contract
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
Popover
from
'
ui/shared/chakra/Popover
'
;
import
FormField
FancySelect
from
'
ui/shared/forms/fields/FormFieldFancy
Select
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
Tooltip
}
from
'
toolkit/chakra/tooltip
'
;
import
FormField
Select
from
'
ui/shared/forms/fields/FormField
Select
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
METHOD_LABELS
}
from
'
../utils
'
;
...
...
@@ -29,95 +21,87 @@ interface Props {
}
const
ContractVerificationFieldMethod
=
({
methods
}:
Props
)
=>
{
const
tooltipBg
=
useColorModeValue
(
'
gray.700
'
,
'
gray.900
'
);
const
isMobile
=
useIsMobile
();
const
options
=
React
.
useMemo
(()
=>
methods
.
map
((
method
)
=>
({
value
:
method
,
label
:
METHOD_LABELS
[
method
],
})),
[
methods
]);
const
collection
=
React
.
useMemo
(()
=>
createListCollection
({
items
:
methods
.
map
((
method
)
=>
({
value
:
method
,
label
:
METHOD_LABELS
[
method
],
})),
}),
[
methods
]);
const
renderPopoverListItem
=
React
.
useCallback
((
method
:
SmartContractVerificationMethod
)
=>
{
switch
(
method
)
{
case
'
flattened-code
'
:
return
<
List
Item
key=
{
method
}
>
Verification through a single file.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification through a single file.
</
List
.
Item
>;
case
'
multi-part
'
:
return
<
List
Item
key=
{
method
}
>
Verification of multi-part Solidity files.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification of multi-part Solidity files.
</
List
.
Item
>;
case
'
sourcify
'
:
return
<
List
Item
key=
{
method
}
>
Verification through
<
Link
href=
"https://sourcify.dev/"
target=
"_blank"
>
Sourcify
</
Link
>
.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification through
<
Link
href=
"https://sourcify.dev/"
target=
"_blank"
className=
"dark"
>
Sourcify
</
Link
>
.
</
List
.
Item
>;
case
'
standard-input
'
:
return
(
<
ListItem
key=
{
method
}
>
<
List
.
Item
key=
{
method
}
>
<
span
>
Verification using
</
span
>
<
Link
href=
"https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description"
target=
"_blank"
className=
"dark"
>
Standard input JSON
</
Link
>
<
span
>
file.
</
span
>
</
ListItem
>
</
List
.
Item
>
);
case
'
vyper-code
'
:
return
<
List
Item
key=
{
method
}
>
Verification of Vyper contract.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification of Vyper contract.
</
List
.
Item
>;
case
'
vyper-multi-part
'
:
return
<
List
Item
key=
{
method
}
>
Verification of multi-part Vyper files.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification of multi-part Vyper files.
</
List
.
Item
>;
case
'
vyper-standard-input
'
:
return
(
<
ListItem
key=
{
method
}
>
<
List
.
Item
key=
{
method
}
>
<
span
>
Verification of Vyper contract using
</
span
>
<
Link
href=
"https://docs.vyperlang.org/en/stable/compiling-a-contract.html#compiler-input-and-output-json-description"
target=
"_blank"
className=
"dark"
>
Standard input JSON
</
Link
>
<
span
>
file.
</
span
>
</
ListItem
>
</
List
.
Item
>
);
case
'
solidity-hardhat
'
:
return
<
List
Item
key=
{
method
}
>
Verification through Hardhat plugin.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification through Hardhat plugin.
</
List
.
Item
>;
case
'
solidity-foundry
'
:
return
<
List
Item
key=
{
method
}
>
Verification through Foundry.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification through Foundry.
</
List
.
Item
>;
case
'
stylus-github-repository
'
:
return
<
List
Item
key=
{
method
}
>
Verification of Stylus contract via GitHub repository.
</
List
Item
>;
return
<
List
.
Item
key=
{
method
}
>
Verification of Stylus contract via GitHub repository.
</
List
.
Item
>;
}
},
[]);
const
tooltipContent
=
(
<
Box
>
<
span
>
Currently, Blockscout supports
{
methods
.
length
}
methods:
</
span
>
<
List
.
Root
as=
"ol"
pl=
{
5
}
>
{
methods
.
map
(
renderPopoverListItem
)
}
</
List
.
Root
>
</
Box
>
);
return
(
<>
<
Box
mt=
{
{
base
:
10
,
lg
:
6
}
}
gridColumn=
{
{
lg
:
'
1 / 3
'
}
}
>
<
chakra
.
span
fontWeight=
{
500
}
fontSize=
"lg"
fontFamily=
"heading"
>
Currently, Blockscout supports
{
methods
.
length
}
contract verification methods
</
chakra
.
span
>
<
Popover
trigger=
"hover"
isLazy
placement=
{
isMobile
?
'
bottom-end
'
:
'
right-start
'
}
offset=
{
[
-
8
,
8
]
}
>
<
PopoverTrigger
>
<
chakra
.
span
display=
"inline-block"
ml=
{
1
}
cursor=
"pointer"
verticalAlign=
"middle"
h=
"22px"
>
<
IconSvg
name=
"info"
boxSize=
{
5
}
color=
"icon_info"
_hover=
{
{
color
:
'
link_hovered
'
}
}
/>
</
chakra
.
span
>
</
PopoverTrigger
>
<
Portal
>
<
PopoverContent
bgColor=
{
tooltipBg
}
w=
{
{
base
:
'
300px
'
,
lg
:
'
380px
'
}
}
>
<
PopoverArrow
bgColor=
{
tooltipBg
}
/>
<
PopoverBody
color=
"white"
>
<
DarkMode
>
<
span
>
Currently, Blockscout supports
{
methods
.
length
}
methods:
</
span
>
<
OrderedList
>
{
methods
.
map
(
renderPopoverListItem
)
}
</
OrderedList
>
</
DarkMode
>
</
PopoverBody
>
</
PopoverContent
>
</
Portal
>
</
Popover
>
<
Tooltip
content=
{
tooltipContent
}
interactive
contentProps=
{
{
textAlign
:
'
left
'
,
className
:
'
light
'
}
}
>
<
IconSvg
name=
"info"
boxSize=
{
5
}
ml=
{
1
}
cursor=
"pointer"
color=
"icon.info"
_hover=
{
{
color
:
'
link.primary.hover
'
}
}
/>
</
Tooltip
>
</
Box
>
<
FormField
Fancy
Select
<
FormFields
,
'
method
'
>
<
FormFieldSelect
<
FormFields
,
'
method
'
>
name="method"
placeholder="Verification method (compiler type)"
options=
{
options
}
isRequired
isAsync=
{
false
}
isReadOnly=
{
options
.
length
===
1
}
collection=
{
collection
}
required
readOnly=
{
collection
.
items
.
length
===
1
}
/
>
</>
);
...
...
ui/contractVerification/fields/ContractVerificationFieldName.tsx
View file @
532f7e7a
...
...
@@ -16,9 +16,8 @@ const ContractVerificationFieldName = ({ hint }: Props) => {
<
ContractVerificationFormRow
>
<
FormFieldText
<
FormFields
>
name="name"
isR
equired
r
equired
placeholder="Contract name"
size=
{
{
base
:
'
md
'
,
lg
:
'
lg
'
}
}
rules=
{
{
maxLength
:
255
}
}
/
>
{
hint
?
<
span
>
{
hint
}
</
span
>
:
(
...
...
ui/contractVerification/fields/ContractVerificationFieldOptimization.tsx
View file @
532f7e7a
...
...
@@ -27,10 +27,12 @@ const ContractVerificationFieldOptimization = () => {
{
isEnabled
&&
(
<
FormFieldText
<
FormFields
,
'
optimization_runs
'
>
name="optimization_runs"
isR
equired
r
equired
placeholder="Optimization runs"
type="number"
size="xs"
inputProps=
{
{
type
:
'
number
'
,
}
}
size="sm"
minW="100px"
maxW="200px"
flexShrink=
{
1
}
...
...
ui/contractVerification/types.ts
View file @
532f7e7a
...
...
@@ -7,11 +7,6 @@ export interface ContractLibrary {
address
:
string
;
}
interface
MethodOption
{
label
:
string
;
value
:
SmartContractVerificationMethod
;
}
export
interface
LicenseOption
{
label
:
string
;
value
:
SmartContractLicenseType
;
...
...
@@ -19,15 +14,15 @@ export interface LicenseOption {
interface
FormFieldsBase
{
address
:
string
;
method
:
MethodOption
;
license_type
:
LicenseOption
|
null
;
method
:
Array
<
SmartContractVerificationMethod
>
;
license_type
:
Array
<
SmartContractLicenseType
>
;
}
export
interface
FormFieldsFlattenSourceCode
extends
FormFieldsBase
{
is_yul
:
boolean
;
name
:
string
|
undefined
;
compiler
:
Option
|
null
;
evm_version
:
Option
|
null
;
compiler
:
Array
<
string
>
;
evm_version
:
Array
<
string
>
;
is_optimization_enabled
:
boolean
;
optimization_runs
:
string
;
code
:
string
;
...
...
@@ -38,7 +33,7 @@ export interface FormFieldsFlattenSourceCode extends FormFieldsBase {
export
interface
FormFieldsStandardInput
extends
FormFieldsBase
{
name
:
string
;
compiler
:
Option
|
null
;
compiler
:
Array
<
string
>
;
sources
:
Array
<
File
>
;
autodetect_constructor_args
:
boolean
;
constructor_args
:
string
;
...
...
@@ -46,8 +41,8 @@ export interface FormFieldsStandardInput extends FormFieldsBase {
export
interface
FormFieldsStandardInputZk
extends
FormFieldsBase
{
name
:
string
;
compiler
:
Option
|
null
;
zk_compiler
:
Option
|
null
;
compiler
:
Array
<
string
>
;
zk_compiler
:
Array
<
string
>
;
sources
:
Array
<
File
>
;
autodetect_constructor_args
:
boolean
;
constructor_args
:
string
;
...
...
@@ -59,8 +54,8 @@ export interface FormFieldsSourcify extends FormFieldsBase {
}
export
interface
FormFieldsMultiPartFile
extends
FormFieldsBase
{
compiler
:
Option
|
null
;
evm_version
:
Option
|
null
;
compiler
:
Array
<
string
>
;
evm_version
:
Array
<
string
>
;
is_optimization_enabled
:
boolean
;
optimization_runs
:
string
;
sources
:
Array
<
File
>
;
...
...
@@ -69,26 +64,26 @@ export interface FormFieldsMultiPartFile extends FormFieldsBase {
export
interface
FormFieldsVyperContract
extends
FormFieldsBase
{
name
:
string
;
evm_version
:
Option
|
null
;
compiler
:
Option
|
null
;
evm_version
:
Array
<
string
>
;
compiler
:
Array
<
string
>
;
code
:
string
;
constructor_args
:
string
|
undefined
;
}
export
interface
FormFieldsVyperMultiPartFile
extends
FormFieldsBase
{
compiler
:
Option
|
null
;
evm_version
:
Option
|
null
;
compiler
:
Array
<
string
>
;
evm_version
:
Array
<
string
>
;
sources
:
Array
<
File
>
;
interfaces
:
Array
<
File
>
;
}
export
interface
FormFieldsVyperStandardInput
extends
FormFieldsBase
{
compiler
:
Option
|
null
;
compiler
:
Array
<
string
>
;
sources
:
Array
<
File
>
;
}
export
interface
FormFieldsStylusGitHubRepo
extends
FormFieldsBase
{
compiler
:
Option
|
null
;
compiler
:
Array
<
string
>
;
repository_url
:
string
;
commit_hash
:
string
;
path_prefix
:
string
;
...
...
ui/contractVerification/utils.ts
View file @
532f7e7a
...
...
@@ -51,123 +51,93 @@ export const METHOD_LABELS: Record<SmartContractVerificationMethod, string> = {
export
const
DEFAULT_VALUES
:
Record
<
SmartContractVerificationMethod
,
FormFields
>
=
{
'
flattened-code
'
:
{
address
:
''
,
method
:
{
value
:
'
flattened-code
'
as
const
,
label
:
METHOD_LABELS
[
'
flattened-code
'
],
},
method
:
[
'
flattened-code
'
],
is_yul
:
false
,
name
:
''
,
compiler
:
null
,
evm_version
:
null
,
compiler
:
[]
,
evm_version
:
[]
,
is_optimization_enabled
:
true
,
optimization_runs
:
'
200
'
,
code
:
''
,
autodetect_constructor_args
:
true
,
constructor_args
:
''
,
libraries
:
[],
license_type
:
null
,
license_type
:
[]
,
},
'
standard-input
'
:
{
address
:
''
,
method
:
{
value
:
'
standard-input
'
as
const
,
label
:
METHOD_LABELS
[
'
standard-input
'
],
},
method
:
[
'
standard-input
'
],
name
:
''
,
compiler
:
null
,
compiler
:
[]
,
sources
:
[],
autodetect_constructor_args
:
true
,
constructor_args
:
''
,
license_type
:
null
,
license_type
:
[]
,
},
sourcify
:
{
address
:
''
,
method
:
{
value
:
'
sourcify
'
as
const
,
label
:
METHOD_LABELS
.
sourcify
,
},
method
:
[
'
sourcify
'
],
sources
:
[],
license_type
:
null
,
license_type
:
[]
,
},
'
multi-part
'
:
{
address
:
''
,
method
:
{
value
:
'
multi-part
'
as
const
,
label
:
METHOD_LABELS
[
'
multi-part
'
],
},
compiler
:
null
,
evm_version
:
null
,
method
:
[
'
multi-part
'
],
compiler
:
[],
evm_version
:
[],
is_optimization_enabled
:
true
,
optimization_runs
:
'
200
'
,
sources
:
[],
libraries
:
[],
license_type
:
null
,
license_type
:
[]
,
},
'
vyper-code
'
:
{
address
:
''
,
method
:
{
value
:
'
vyper-code
'
as
const
,
label
:
METHOD_LABELS
[
'
vyper-code
'
],
},
method
:
[
'
vyper-code
'
],
name
:
''
,
compiler
:
null
,
evm_version
:
null
,
compiler
:
[]
,
evm_version
:
[]
,
code
:
''
,
constructor_args
:
''
,
license_type
:
null
,
license_type
:
[]
,
},
'
vyper-multi-part
'
:
{
address
:
''
,
method
:
{
value
:
'
vyper-multi-part
'
as
const
,
label
:
METHOD_LABELS
[
'
vyper-multi-part
'
],
},
compiler
:
null
,
evm_version
:
null
,
method
:
[
'
vyper-multi-part
'
],
compiler
:
[],
evm_version
:
[],
sources
:
[],
license_type
:
null
,
license_type
:
[]
,
},
'
vyper-standard-input
'
:
{
address
:
''
,
method
:
{
value
:
'
vyper-standard-input
'
as
const
,
label
:
METHOD_LABELS
[
'
vyper-standard-input
'
],
},
compiler
:
null
,
method
:
[
'
vyper-standard-input
'
],
compiler
:
[],
sources
:
[],
license_type
:
null
,
license_type
:
[]
,
},
'
solidity-hardhat
'
:
{
address
:
''
,
method
:
{
value
:
'
solidity-hardhat
'
as
const
,
label
:
METHOD_LABELS
[
'
solidity-hardhat
'
],
},
compiler
:
null
,
method
:
[
'
solidity-hardhat
'
],
compiler
:
[],
sources
:
[],
license_type
:
null
,
license_type
:
[]
,
},
'
solidity-foundry
'
:
{
address
:
''
,
method
:
{
value
:
'
solidity-foundry
'
as
const
,
label
:
METHOD_LABELS
[
'
solidity-foundry
'
],
},
compiler
:
null
,
method
:
[
'
solidity-foundry
'
],
compiler
:
[],
sources
:
[],
license_type
:
null
,
license_type
:
[]
,
},
'
stylus-github-repository
'
:
{
address
:
''
,
method
:
{
value
:
'
stylus-github-repository
'
as
const
,
label
:
METHOD_LABELS
[
'
stylus-github-repository
'
],
},
compiler
:
null
,
method
:
[
'
stylus-github-repository
'
],
compiler
:
[],
repository_url
:
''
,
commit_hash
:
''
,
path_prefix
:
''
,
license_type
:
null
,
license_type
:
[]
,
},
};
...
...
@@ -188,11 +158,11 @@ export function getDefaultValues(
if
(
'
evm_version
'
in
defaultValues
)
{
if
(
method
===
'
flattened-code
'
||
method
===
'
multi-part
'
)
{
defaultValues
.
evm_version
=
config
.
solidity_evm_versions
.
find
((
value
)
=>
value
===
'
default
'
)
?
{
label
:
'
default
'
,
value
:
'
default
'
}
:
null
;
defaultValues
.
evm_version
=
config
.
solidity_evm_versions
.
find
((
value
)
=>
value
===
'
default
'
)
?
[
'
default
'
]
:
[]
;
}
if
(
method
===
'
vyper-multi-part
'
)
{
defaultValues
.
evm_version
=
config
.
vyper_evm_versions
.
find
((
value
)
=>
value
===
'
default
'
)
?
{
label
:
'
default
'
,
value
:
'
default
'
}
:
null
;
defaultValues
.
evm_version
=
config
.
vyper_evm_versions
.
find
((
value
)
=>
value
===
'
default
'
)
?
[
'
default
'
]
:
[]
;
}
}
...
...
@@ -204,10 +174,7 @@ export function getDefaultValues(
}
if
(
singleMethod
)
{
defaultValues
.
method
=
{
label
:
METHOD_LABELS
[
config
.
verification_options
[
0
]],
value
:
config
.
verification_options
[
0
],
};
defaultValues
.
method
=
config
.
verification_options
;
}
return
defaultValues
;
...
...
@@ -235,21 +202,21 @@ export function sortVerificationMethods(methodA: SmartContractVerificationMethod
export
function
prepareRequestBody
(
data
:
FormFields
):
FetchParams
[
'
body
'
]
{
const
defaultLicenseType
:
SmartContractLicenseType
=
'
none
'
;
switch
(
data
.
method
.
value
)
{
switch
(
data
.
method
[
0
]
)
{
case
'
flattened-code
'
:
{
const
_data
=
data
as
FormFieldsFlattenSourceCode
;
return
{
compiler_version
:
_data
.
compiler
?.
value
,
compiler_version
:
_data
.
compiler
?.
[
0
]
,
source_code
:
_data
.
code
,
is_optimization_enabled
:
_data
.
is_optimization_enabled
,
is_yul_contract
:
_data
.
is_yul
,
optimization_runs
:
_data
.
optimization_runs
,
contract_name
:
_data
.
name
||
undefined
,
libraries
:
reduceLibrariesArray
(
_data
.
libraries
),
evm_version
:
_data
.
evm_version
?.
value
,
evm_version
:
_data
.
evm_version
?.
[
0
]
,
autodetect_constructor_args
:
_data
.
autodetect_constructor_args
,
constructor_args
:
_data
.
constructor_args
,
license_type
:
_data
.
license_type
?.
value
??
defaultLicenseType
,
license_type
:
_data
.
license_type
?.
[
0
]
??
defaultLicenseType
,
};
}
...
...
@@ -257,15 +224,15 @@ export function prepareRequestBody(data: FormFields): FetchParams['body'] {
const
_data
=
data
as
(
FormFieldsStandardInput
|
FormFieldsStandardInputZk
);
const
body
=
new
FormData
();
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
.
value
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
value
??
defaultLicenseType
);
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
?.[
0
]
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
[
0
]
??
defaultLicenseType
);
body
.
set
(
'
contract_name
'
,
_data
.
name
);
body
.
set
(
'
autodetect_constructor_args
'
,
String
(
Boolean
(
_data
.
autodetect_constructor_args
)));
body
.
set
(
'
constructor_args
'
,
_data
.
constructor_args
);
addFilesToFormData
(
body
,
_data
.
sources
,
'
files
'
);
// zkSync fields
'
zk_compiler
'
in
_data
&&
_data
.
zk_compiler
&&
body
.
set
(
'
zk_compiler_version
'
,
_data
.
zk_compiler
.
value
);
'
zk_compiler
'
in
_data
&&
_data
.
zk_compiler
&&
body
.
set
(
'
zk_compiler_version
'
,
_data
.
zk_compiler
?.[
0
]
);
return
body
;
}
...
...
@@ -274,8 +241,8 @@ export function prepareRequestBody(data: FormFields): FetchParams['body'] {
const
_data
=
data
as
FormFieldsSourcify
;
const
body
=
new
FormData
();
addFilesToFormData
(
body
,
_data
.
sources
,
'
files
'
);
body
.
set
(
'
chosen_contract_index
'
,
_data
.
contract_index
?.
value
??
defaultLicenseType
);
_data
.
license_type
&&
body
.
set
(
'
license_type
'
,
_data
.
license_type
.
valu
e
);
body
.
set
(
'
chosen_contract_index
'
,
_data
.
contract_index
?.
value
??
'
0
'
);
_data
.
license_type
&&
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.[
0
]
??
defaultLicenseTyp
e
);
return
body
;
}
...
...
@@ -284,9 +251,9 @@ export function prepareRequestBody(data: FormFields): FetchParams['body'] {
const
_data
=
data
as
FormFieldsMultiPartFile
;
const
body
=
new
FormData
();
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
.
value
);
_data
.
evm_version
&&
body
.
set
(
'
evm_version
'
,
_data
.
evm_version
.
value
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
value
??
defaultLicenseType
);
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
?.[
0
]
);
_data
.
evm_version
&&
body
.
set
(
'
evm_version
'
,
_data
.
evm_version
?.[
0
]
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
[
0
]
??
defaultLicenseType
);
body
.
set
(
'
is_optimization_enabled
'
,
String
(
Boolean
(
_data
.
is_optimization_enabled
)));
_data
.
is_optimization_enabled
&&
body
.
set
(
'
optimization_runs
'
,
_data
.
optimization_runs
);
...
...
@@ -301,12 +268,12 @@ export function prepareRequestBody(data: FormFields): FetchParams['body'] {
const
_data
=
data
as
FormFieldsVyperContract
;
return
{
compiler_version
:
_data
.
compiler
?.
value
,
evm_version
:
_data
.
evm_version
?.
value
,
compiler_version
:
_data
.
compiler
?.
[
0
]
,
evm_version
:
_data
.
evm_version
?.
[
0
]
,
source_code
:
_data
.
code
,
contract_name
:
_data
.
name
,
constructor_args
:
_data
.
constructor_args
,
license_type
:
_data
.
license_type
?.
value
??
defaultLicenseType
,
license_type
:
_data
.
license_type
?.
[
0
]
??
defaultLicenseType
,
};
}
...
...
@@ -314,9 +281,9 @@ export function prepareRequestBody(data: FormFields): FetchParams['body'] {
const
_data
=
data
as
FormFieldsVyperMultiPartFile
;
const
body
=
new
FormData
();
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
.
value
);
_data
.
evm_version
&&
body
.
set
(
'
evm_version
'
,
_data
.
evm_version
.
value
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
value
??
defaultLicenseType
);
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
?.[
0
]
);
_data
.
evm_version
&&
body
.
set
(
'
evm_version
'
,
_data
.
evm_version
?.[
0
]
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
[
0
]
??
defaultLicenseType
);
addFilesToFormData
(
body
,
_data
.
sources
,
'
files
'
);
addFilesToFormData
(
body
,
_data
.
interfaces
,
'
interfaces
'
);
...
...
@@ -327,8 +294,8 @@ export function prepareRequestBody(data: FormFields): FetchParams['body'] {
const
_data
=
data
as
FormFieldsVyperStandardInput
;
const
body
=
new
FormData
();
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
.
value
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
value
??
defaultLicenseType
);
_data
.
compiler
&&
body
.
set
(
'
compiler_version
'
,
_data
.
compiler
?.[
0
]
);
body
.
set
(
'
license_type
'
,
_data
.
license_type
?.
[
0
]
??
defaultLicenseType
);
addFilesToFormData
(
body
,
_data
.
sources
,
'
files
'
);
return
body
;
...
...
@@ -338,11 +305,11 @@ export function prepareRequestBody(data: FormFields): FetchParams['body'] {
const
_data
=
data
as
FormFieldsStylusGitHubRepo
;
return
{
cargo_stylus_version
:
_data
.
compiler
?.
value
,
cargo_stylus_version
:
_data
.
compiler
?.
[
0
]
,
repository_url
:
_data
.
repository_url
,
commit
:
_data
.
commit_hash
,
path_prefix
:
_data
.
path_prefix
,
license_type
:
_data
.
license_type
?.
value
??
defaultLicenseType
,
license_type
:
_data
.
license_type
?.
[
0
]
??
defaultLicenseType
,
};
}
...
...
ui/pages/ContractVerificationForAddress.tsx
View file @
532f7e7a
...
...
@@ -93,6 +93,8 @@ const ContractVerificationForAddress = () => {
fontSize=
"lg"
fontWeight=
{
500
}
mb=
{
12
}
w=
"min-content"
maxW=
"100%"
/>
{
content
}
</>
...
...
ui/pages/VerifiedAddresses.tsx
View file @
532f7e7a
...
...
@@ -207,8 +207,8 @@ const VerifiedAddresses = () => {
Before starting, make sure that:
</
chakra
.
p
>
<
List
.
Root
ml=
{
6
}
as=
"ol"
>
<
List
.
Item
_marker=
{
{
color
:
'
inherit
'
}
}
>
The source code for the smart contract is deployed on “
{
config
.
chain
.
name
}
”.
</
List
.
Item
>
<
List
.
Item
_marker=
{
{
color
:
'
inherit
'
}
}
>
<
List
.
Item
>
The source code for the smart contract is deployed on “
{
config
.
chain
.
name
}
”.
</
List
.
Item
>
<
List
.
Item
>
<
span
>
The source code is verified (if not yet verified, you can use
</
span
>
<
Link
href=
"https://docs.blockscout.com/for-users/verifying-a-smart-contract"
target=
"_blank"
>
this tool
</
Link
>
<
span
>
).
</
span
>
...
...
ui/shared/forms/fields/FormFieldText.tsx
View file @
532f7e7a
...
...
@@ -31,10 +31,15 @@ const FormFieldText = <
group
,
inputProps
,
asComponent
,
size
=
asComponent
===
'
Textarea
'
?
'
2xl
'
:
'
xl
'
,
size
:
sizeProp
,
disabled
,
floating
:
floatingProp
,
...
restProps
}
: Props
<
FormFields
,
Name
>
) =
>
{
const
defaultSize
=
asComponent
===
'
Textarea
'
?
'
2xl
'
:
'
xl
'
;
const
size
=
sizeProp
||
defaultSize
;
const
floating
=
floatingProp
!==
undefined
?
floatingProp
:
size
===
defaultSize
;
const
{
control
}
=
useFormContext
<
FormFields
>
();
const
{
field
,
fieldState
,
formState
}
=
useController
<
FormFields
,
typeof
name
>
({
control
,
...
...
@@ -59,6 +64,8 @@ const FormFieldText = <
<
Input
{
...
field
}
autoComplete=
"off"
// for non-floating field label, we pass placeholder to the input component
placeholder=
{
!
floating
?
placeholder
:
undefined
}
{
...
inputProps
as
InputProps
}
onBlur=
{
handleBlur
}
/>
...
...
@@ -75,12 +82,13 @@ const FormFieldText = <
return
(
<
Field
label=
{
placeholder
}
// for floating field label, we pass placeholder value to the label
label=
{
floating
?
placeholder
:
undefined
}
errorText=
{
getFieldErrorText
(
fieldState
.
error
)
}
invalid=
{
Boolean
(
fieldState
.
error
)
}
disabled=
{
formState
.
isSubmitting
||
disabled
}
size=
{
size
}
floating
floating
=
{
floating
}
{
...
restProps
}
>
{
content
}
...
...
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