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
0b4b78da
Commit
0b4b78da
authored
Feb 27, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
page base layout and filters
parent
0f0b0b2b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
227 additions
and
8 deletions
+227
-8
resources.ts
lib/api/resources.ts
+11
-1
verified-contracts.tsx
pages/verified-contracts.tsx
+18
-6
contracts.ts
types/api/contracts.ts
+26
-0
VerifiedContracts.tsx
ui/pages/VerifiedContracts.tsx
+127
-0
PageTitle.tsx
ui/shared/Page/PageTitle.tsx
+1
-1
VerifiedContractsFilter.tsx
ui/verifiedContracts/VerifiedContractsFilter.tsx
+44
-0
No files found.
lib/api/resources.ts
View file @
0b4b78da
...
@@ -17,6 +17,7 @@ import type { AddressesResponse } from 'types/api/addresses';
...
@@ -17,6 +17,7 @@ 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
,
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
type
{
SmartContract
,
SmartContractReadMethod
,
SmartContractWriteMethod
,
SmartContractVerificationConfig
}
from
'
types/api/contract
'
;
import
type
{
VerifiedContractsResponse
,
VerifiedContractsFilters
}
from
'
types/api/contracts
'
;
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
'
;
...
@@ -258,6 +259,12 @@ export const RESOURCES = {
...
@@ -258,6 +259,12 @@ export const RESOURCES = {
pathParams
:
[
'
hash
'
as
const
,
'
method
'
as
const
],
pathParams
:
[
'
hash
'
as
const
,
'
method
'
as
const
],
},
},
verified_contracts
:
{
path
:
'
/api/v2/smart-contracts
'
,
paginationFields
:
[
'
items_count
'
as
const
,
'
smart_contract_id
'
as
const
],
filterFields
:
[
'
q
'
as
const
,
'
filter
'
as
const
],
},
// TOKEN
// TOKEN
token
:
{
token
:
{
path
:
'
/api/v2/tokens/:hash
'
,
path
:
'
/api/v2/tokens/:hash
'
,
...
@@ -399,7 +406,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
...
@@ -399,7 +406,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
'
search
'
|
'
search
'
|
'
address_logs
'
|
'
address_tokens
'
|
'
address_logs
'
|
'
address_tokens
'
|
'
token_transfers
'
|
'
token_holders
'
|
'
token_inventory
'
|
'
tokens
'
|
'
token_transfers
'
|
'
token_holders
'
|
'
token_inventory
'
|
'
tokens
'
|
'
token_instance_transfers
'
;
'
token_instance_transfers
'
|
'
verified_contracts
'
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
...
@@ -457,6 +465,7 @@ Q extends 'contract_methods_read' ? Array<SmartContractReadMethod> :
...
@@ -457,6 +465,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
'
verified_contracts
'
?
VerifiedContractsResponse
:
Q
extends
'
visualize_sol2uml
'
?
VisualizedContract
:
Q
extends
'
visualize_sol2uml
'
?
VisualizedContract
:
Q
extends
'
contract_verification_config
'
?
SmartContractVerificationConfig
:
Q
extends
'
contract_verification_config
'
?
SmartContractVerificationConfig
:
never
;
never
;
...
@@ -473,5 +482,6 @@ Q extends 'address_token_transfers' ? AddressTokenTransferFilters :
...
@@ -473,5 +482,6 @@ Q extends 'address_token_transfers' ? AddressTokenTransferFilters :
Q
extends
'
address_tokens
'
?
AddressTokensFilter
:
Q
extends
'
address_tokens
'
?
AddressTokensFilter
:
Q
extends
'
search
'
?
SearchResultFilters
:
Q
extends
'
search
'
?
SearchResultFilters
:
Q
extends
'
tokens
'
?
TokensFilters
:
Q
extends
'
tokens
'
?
TokensFilters
:
Q
extends
'
verified_contracts
'
?
VerifiedContractsFilters
:
never
;
never
;
/* eslint-enable @typescript-eslint/indent */
/* eslint-enable @typescript-eslint/indent */
pages/verified-contracts.tsx
View file @
0b4b78da
import
type
{
NextPage
}
from
'
next
'
;
import
type
{
NextPage
}
from
'
next
'
;
import
Head
from
'
next/head
'
;
import
React
from
'
react
'
;
import
getNetworkTitle
from
'
lib/networks/getNetworkTitle
'
;
import
VerifiedContracts
from
'
ui/pages/VerifiedContracts
'
;
import
Page
from
'
ui/shared/Page/Page
'
;
const
VerifiedContractsPage
:
NextPage
=
()
=>
{
const
VerifiedContractsPage
:
NextPage
=
()
=>
{
return
null
;
const
title
=
getNetworkTitle
();
return
(
<>
<
Head
>
<
title
>
{
title
}
</
title
>
</
Head
>
<
Page
>
<
VerifiedContracts
/>
</
Page
>
</>
);
};
};
export
default
VerifiedContractsPage
;
export
default
VerifiedContractsPage
;
export
async
function
getServerSideProps
()
{
export
{
getServerSideProps
}
from
'
lib/next/getServerSideProps
'
;
return
{
notFound
:
true
,
};
}
types/api/contracts.ts
0 → 100644
View file @
0b4b78da
import
type
{
AddressParam
}
from
'
./addressParams
'
;
export
interface
VerifiedContract
{
address
:
AddressParam
;
coin_balance
:
string
;
compiler_version
:
string
;
language
:
'
vyper
'
|
'
yul
'
|
'
solidity
'
;
has_constructor_args
:
boolean
;
optimization_enabled
:
boolean
;
tx_count
:
number
;
verified_at
:
string
;
market_cap
:
string
|
null
;
}
export
interface
VerifiedContractsResponse
{
items
:
Array
<
VerifiedContract
>
;
next_page_params
:
{
items_count
:
string
;
smart_contract_id
:
string
;
}
|
null
;
}
export
interface
VerifiedContractsFilters
{
q
:
string
|
undefined
;
filter
:
'
vyper
'
|
'
solidity
'
|
undefined
;
}
ui/pages/VerifiedContracts.tsx
0 → 100644
View file @
0b4b78da
import
{
Box
,
Flex
,
Hide
,
Show
,
Text
}
from
'
@chakra-ui/react
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
VerifiedContractsFilters
}
from
'
types/api/contracts
'
;
import
useDebounce
from
'
lib/hooks/useDebounce
'
;
import
useQueryWithPages
from
'
lib/hooks/useQueryWithPages
'
;
import
{
apos
}
from
'
lib/html-entities
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
EmptySearchResult
from
'
ui/apps/EmptySearchResult
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
FilterInput
from
'
ui/shared/filters/FilterInput
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
Pagination
from
'
ui/shared/Pagination
'
;
import
SkeletonList
from
'
ui/shared/skeletons/SkeletonList
'
;
import
SkeletonTable
from
'
ui/shared/skeletons/SkeletonTable
'
;
import
VerifiedContractsFilter
from
'
ui/verifiedContracts/VerifiedContractsFilter
'
;
const
VerifiedContracts
=
()
=>
{
const
router
=
useRouter
();
const
[
searchTerm
,
setSearchTerm
]
=
React
.
useState
(
getQueryParamString
(
router
.
query
.
q
)
||
undefined
);
const
[
type
,
setType
]
=
React
.
useState
(
getQueryParamString
(
router
.
query
.
filter
)
as
VerifiedContractsFilters
[
'
filter
'
]
||
undefined
);
const
debouncedSearchTerm
=
useDebounce
(
searchTerm
||
''
,
300
);
const
{
isError
,
isLoading
,
data
,
isPaginationVisible
,
pagination
,
onFilterChange
}
=
useQueryWithPages
({
resourceName
:
'
verified_contracts
'
,
filters
:
{
q
:
debouncedSearchTerm
,
filter
:
type
},
});
const
handleSearchTemChange
=
React
.
useCallback
((
value
:
string
)
=>
{
onFilterChange
({
q
:
value
,
filter
:
type
});
setSearchTerm
(
value
);
},
[
type
,
onFilterChange
]);
const
handleTypeChange
=
React
.
useCallback
((
value
:
string
|
Array
<
string
>
)
=>
{
if
(
Array
.
isArray
(
value
))
{
return
;
}
if
((
value
===
'
vyper
'
||
value
===
'
solidity
'
))
{
onFilterChange
({
q
:
debouncedSearchTerm
,
filter
:
value
});
setType
(
value
);
return
;
}
onFilterChange
({
q
:
debouncedSearchTerm
,
filter
:
undefined
});
setType
(
undefined
);
},
[
debouncedSearchTerm
,
onFilterChange
]);
const
typeFilter
=
<
VerifiedContractsFilter
onChange=
{
handleTypeChange
}
defaultValue=
{
type
}
isActive=
{
Boolean
(
type
)
}
/>;
const
filterInput
=
(
<
FilterInput
w=
{
{
base
:
'
100%
'
,
lg
:
'
350px
'
}
}
size=
"xs"
onChange=
{
handleSearchTemChange
}
placeholder=
"Search by contract name or address"
initialValue=
{
searchTerm
}
/>
);
const
bar
=
(
<>
<
Flex
columnGap=
{
3
}
mb=
{
6
}
display=
{
{
base
:
'
flex
'
,
lg
:
'
none
'
}
}
>
{
typeFilter
}
{
filterInput
}
</
Flex
>
<
ActionBar
mt=
{
-
6
}
>
<
Flex
columnGap=
{
3
}
display=
{
{
base
:
'
none
'
,
lg
:
'
flex
'
}
}
>
{
typeFilter
}
{
filterInput
}
</
Flex
>
{
isPaginationVisible
&&
<
Pagination
ml=
"auto"
{
...
pagination
}
/>
}
</
ActionBar
>
</>
);
const
content
=
(()
=>
{
if
(
isError
)
{
return
<
DataFetchAlert
/>;
}
if
(
isLoading
)
{
return
(
<>
<
Show
below=
"lg"
ssr=
{
false
}
>
<
SkeletonList
/>
</
Show
>
<
Hide
below=
"lg"
ssr=
{
false
}
>
<
SkeletonTable
columns=
{
[
'
15%
'
,
'
15%
'
,
'
10%
'
,
'
20%
'
,
'
20%
'
,
'
20%
'
]
}
/>
</
Hide
>
</>
);
}
if
(
data
.
items
.
length
===
0
&&
!
searchTerm
)
{
return
<
Text
as=
"span"
>
There are no verified contracts
</
Text
>;
}
if
(
data
.
items
.
length
===
0
)
{
return
<
EmptySearchResult
text=
{
`Couldn${ apos }t find any contract that matches your query.`
}
/>;
}
return
(
<>
<
Show
below=
"lg"
ssr=
{
false
}
>
{
'
<AddressIntTxsList data={ data.items } currentAddress={ hash }/>
'
}
</
Show
>
<
Hide
below=
"lg"
ssr=
{
false
}
>
{
'
<AddressIntTxsTable data={ data.items } currentAddress={ hash }/>
'
}
</
Hide
>
</>
);
})();
return
(
<
Box
>
<
PageTitle
text=
"Verified contracts"
withTextAd
/>
{
bar
}
{
content
}
</
Box
>
);
};
export
default
VerifiedContracts
;
ui/shared/Page/PageTitle.tsx
View file @
0b4b78da
...
@@ -37,7 +37,7 @@ const PageTitle = ({ text, additionalsLeft, additionalsRight, withTextAd, backLi
...
@@ -37,7 +37,7 @@ const PageTitle = ({ text, additionalsLeft, additionalsRight, withTextAd, backLi
justifyContent=
"space-between"
justifyContent=
"space-between"
className=
{
className
}
className=
{
className
}
>
>
<
Flex
flexWrap=
"wrap"
columnGap=
{
3
}
alignItems=
"center"
width=
{
withTextAd
?
'
unset
'
:
'
100%
'
}
>
<
Flex
flexWrap=
"wrap"
columnGap=
{
3
}
alignItems=
"center"
width=
{
withTextAd
?
'
unset
'
:
'
100%
'
}
flexShrink=
{
0
}
>
<
Grid
<
Grid
templateColumns=
{
[
backLinkUrl
&&
'
auto
'
,
additionalsLeft
&&
'
auto
'
,
'
1fr
'
].
filter
(
Boolean
).
join
(
'
'
)
}
templateColumns=
{
[
backLinkUrl
&&
'
auto
'
,
additionalsLeft
&&
'
auto
'
,
'
1fr
'
].
filter
(
Boolean
).
join
(
'
'
)
}
columnGap=
{
3
}
columnGap=
{
3
}
...
...
ui/verifiedContracts/VerifiedContractsFilter.tsx
0 → 100644
View file @
0b4b78da
import
{
Menu
,
MenuButton
,
MenuList
,
MenuOptionGroup
,
MenuItemOption
,
useDisclosure
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
VerifiedContractsFilters
}
from
'
types/api/contracts
'
;
import
FilterButton
from
'
ui/shared/filters/FilterButton
'
;
interface
Props
{
isActive
:
boolean
;
defaultValue
:
VerifiedContractsFilters
[
'
filter
'
]
|
undefined
;
onChange
:
(
nextValue
:
string
|
Array
<
string
>
)
=>
void
;
}
const
VerifiedContractsFilter
=
({
onChange
,
defaultValue
,
isActive
}:
Props
)
=>
{
const
{
isOpen
,
onToggle
}
=
useDisclosure
();
return
(
<
Menu
>
<
MenuButton
>
<
FilterButton
isActive=
{
isOpen
||
isActive
}
onClick=
{
onToggle
}
as=
"div"
/>
</
MenuButton
>
<
MenuList
zIndex=
{
2
}
>
<
MenuOptionGroup
defaultValue=
{
defaultValue
||
'
all
'
}
title=
"Filter"
type=
"radio"
onChange=
{
onChange
}
>
<
MenuItemOption
value=
"all"
>
All
</
MenuItemOption
>
<
MenuItemOption
value=
"solidity"
>
Solidity
</
MenuItemOption
>
<
MenuItemOption
value=
"vyper"
>
Vyper
</
MenuItemOption
>
</
MenuOptionGroup
>
</
MenuList
>
</
Menu
>
);
};
export
default
React
.
memo
(
VerifiedContractsFilter
);
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