Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
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
exchain
nebula
Commits
c725718c
Commit
c725718c
authored
May 30, 2023
by
Will Cory
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(indexer): Add go-chi api
parent
2fdcbd5a
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
264 additions
and
1 deletion
+264
-1
api.go
indexer/api/api.go
+167
-0
api_test.go
indexer/api/api_test.go
+93
-0
go.mod
indexer/go.mod
+2
-1
go.sum
indexer/go.sum
+2
-0
No files found.
indexer/api/api.go
0 → 100644
View file @
c725718c
package
api
import
(
"encoding/json"
"net/http"
"strconv"
"time"
"github.com/go-chi/chi"
)
// Database interface for deposits
type
DepositDB
interface
{
GetDeposits
(
limit
int
,
cursor
string
,
sortDirection
string
)
([]
Deposit
,
string
,
bool
,
error
)
}
// Database interface for withdrawals
type
WithdrawalDB
interface
{
GetWithdrawals
(
limit
int
,
cursor
string
,
sortDirection
string
,
sortBy
string
)
([]
Withdrawal
,
string
,
bool
,
error
)
}
// Deposit data structure
type
Deposit
struct
{
Guid
string
`json:"guid"`
Amount
string
`json:"amount"`
BlockNumber
int
`json:"blockNumber"`
BlockTimestamp
time
.
Time
`json:"blockTimestamp"`
From
string
`json:"from"`
To
string
`json:"to"`
TransactionHash
string
`json:"transactionHash"`
L1Token
TokenListItem
`json:"l1Token"`
L2Token
TokenListItem
`json:"l2Token"`
}
// Withdrawal data structure
type
Withdrawal
struct
{
Guid
string
`json:"guid"`
Amount
string
`json:"amount"`
BlockNumber
int
`json:"blockNumber"`
BlockTimestamp
time
.
Time
`json:"blockTimestamp"`
From
string
`json:"from"`
To
string
`json:"to"`
TransactionHash
string
`json:"transactionHash"`
WithdrawalState
string
`json:"withdrawalState"`
Proof
*
ProofClaim
`json:"proof"`
Claim
*
ProofClaim
`json:"claim"`
L1Token
TokenListItem
`json:"l1Token"`
L2Token
TokenListItem
`json:"l2Token"`
}
// TokenListItem data structure
type
TokenListItem
struct
{
ChainId
int
`json:"chainId"`
Address
string
`json:"address"`
Name
string
`json:"name"`
Symbol
string
`json:"symbol"`
Decimals
int
`json:"decimals"`
LogoURI
string
`json:"logoURI"`
Extensions
Extensions
`json:"extensions"`
}
// Extensions data structure
type
Extensions
struct
{
OptimismBridgeAddress
string
`json:"optimismBridgeAddress"`
BridgeType
string
`json:"bridgeType"`
}
// ProofClaim data structure
type
ProofClaim
struct
{
TransactionHash
string
`json:"transactionHash"`
BlockTimestamp
time
.
Time
`json:"blockTimestamp"`
BlockNumber
int
`json:"blockNumber"`
}
// PaginationResponse for paginated responses
type
PaginationResponse
struct
{
// TODO type this better
Data
interface
{}
`json:"data"`
Cursor
string
`json:"cursor"`
HasNextPage
bool
`json:"hasNextPage"`
}
func
getDepositsHandler
(
depositDB
DepositDB
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
limit
:=
getIntFromQuery
(
r
,
"limit"
,
10
)
cursor
:=
r
.
URL
.
Query
()
.
Get
(
"cursor"
)
sortDirection
:=
r
.
URL
.
Query
()
.
Get
(
"sortDirection"
)
deposits
,
nextCursor
,
hasNextPage
,
err
:=
depositDB
.
GetDeposits
(
limit
,
cursor
,
sortDirection
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
}
response
:=
PaginationResponse
{
Data
:
deposits
,
Cursor
:
nextCursor
,
HasNextPage
:
hasNextPage
,
}
jsonResponse
(
w
,
response
,
http
.
StatusOK
)
}
}
func
getWithdrawalsHandler
(
withdrawalDB
WithdrawalDB
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
limit
:=
getIntFromQuery
(
r
,
"limit"
,
10
)
cursor
:=
r
.
URL
.
Query
()
.
Get
(
"cursor"
)
sortDirection
:=
r
.
URL
.
Query
()
.
Get
(
"sortDirection"
)
sortBy
:=
r
.
URL
.
Query
()
.
Get
(
"sortBy"
)
withdrawals
,
nextCursor
,
hasNextPage
,
err
:=
withdrawalDB
.
GetWithdrawals
(
limit
,
cursor
,
sortDirection
,
sortBy
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
}
response
:=
PaginationResponse
{
Data
:
withdrawals
,
Cursor
:
nextCursor
,
HasNextPage
:
hasNextPage
,
}
jsonResponse
(
w
,
response
,
http
.
StatusOK
)
}
}
func
getIntFromQuery
(
r
*
http
.
Request
,
key
string
,
defaultValue
int
)
int
{
valueStr
:=
r
.
URL
.
Query
()
.
Get
(
key
)
if
valueStr
==
""
{
return
defaultValue
}
value
,
err
:=
strconv
.
Atoi
(
valueStr
)
if
err
!=
nil
{
return
defaultValue
}
return
value
}
func
jsonResponse
(
w
http
.
ResponseWriter
,
data
interface
{},
statusCode
int
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
w
.
WriteHeader
(
statusCode
)
json
.
NewEncoder
(
w
)
.
Encode
(
data
)
}
type
Api
struct
{
Router
*
chi
.
Mux
DepositDB
DepositDB
WithdrawalDB
WithdrawalDB
}
func
NewApi
(
depositDB
DepositDB
,
withdrawalDB
WithdrawalDB
)
*
Api
{
r
:=
chi
.
NewRouter
()
r
.
Get
(
"/api/v0/deposits"
,
getDepositsHandler
(
depositDB
))
r
.
Get
(
"/api/v0/withdrawals"
,
getWithdrawalsHandler
(
withdrawalDB
))
return
&
Api
{
Router
:
r
,
DepositDB
:
depositDB
,
WithdrawalDB
:
withdrawalDB
,
}
}
func
(
a
*
Api
)
Listen
(
port
string
)
{
http
.
ListenAndServe
(
port
,
a
.
Router
)
}
indexer/api/api_test.go
0 → 100644
View file @
c725718c
package
api_test
import
(
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/ethereum-optimism/optimism/indexer/api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
type
MockDB
struct
{
mock
.
Mock
}
func
(
db
*
MockDB
)
GetDeposits
(
limit
int
,
cursor
string
,
sortDirection
string
)
([]
api
.
Deposit
,
string
,
bool
,
error
)
{
args
:=
db
.
Called
(
limit
,
cursor
,
sortDirection
)
return
args
.
Get
(
0
)
.
([]
api
.
Deposit
),
args
.
String
(
1
),
args
.
Bool
(
2
),
args
.
Error
(
3
)
}
func
(
db
*
MockDB
)
GetWithdrawals
(
limit
int
,
cursor
string
,
sortDirection
string
,
sortBy
string
)
([]
api
.
Withdrawal
,
string
,
bool
,
error
)
{
args
:=
db
.
Called
(
limit
,
cursor
,
sortDirection
,
sortBy
)
return
args
.
Get
(
0
)
.
([]
api
.
Withdrawal
),
args
.
String
(
1
),
args
.
Bool
(
2
),
args
.
Error
(
3
)
}
func
TestApi
(
t
*
testing
.
T
)
{
mockDB
:=
new
(
MockDB
)
mockDeposits
:=
[]
api
.
Deposit
{
{
Guid
:
"test-guid"
,
Amount
:
"1000"
,
BlockNumber
:
123
,
BlockTimestamp
:
time
.
Unix
(
123456
,
0
),
From
:
"0x1"
,
To
:
"0x2"
,
TransactionHash
:
"0x3"
,
},
}
mockWithdrawals
:=
[]
api
.
Withdrawal
{
{
Guid
:
"test-guid"
,
Amount
:
"1000"
,
BlockNumber
:
123
,
BlockTimestamp
:
time
.
Unix
(
123456
,
0
),
From
:
"0x1"
,
To
:
"0x2"
,
TransactionHash
:
"0x3"
,
},
}
mockDB
.
On
(
"GetDeposits"
,
10
,
""
,
""
)
.
Return
(
mockDeposits
,
"nextCursor"
,
false
,
nil
)
mockDB
.
On
(
"GetWithdrawals"
,
10
,
""
,
""
,
""
)
.
Return
(
mockWithdrawals
,
"nextCursor"
,
false
,
nil
)
testApi
:=
api
.
NewApi
(
mockDB
,
mockDB
)
req
,
_
:=
http
.
NewRequest
(
"GET"
,
"/api/v0/deposits"
,
nil
)
rr
:=
httptest
.
NewRecorder
()
testApi
.
Router
.
ServeHTTP
(
rr
,
req
)
assert
.
Equal
(
t
,
http
.
StatusOK
,
rr
.
Code
,
"status code should be 200"
)
// TODO make this type exist
var
depositsResponse
api
.
DepositsResponse
err
:=
json
.
Unmarshal
(
rr
.
Body
.
Bytes
(),
&
depositsResponse
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
mockDeposits
,
depositsResponse
.
Data
)
req
,
_
=
http
.
NewRequest
(
"GET"
,
"/api/v0/withdrawals"
,
nil
)
rr
=
httptest
.
NewRecorder
()
testApi
.
Router
.
ServeHTTP
(
rr
,
req
)
assert
.
Equal
(
t
,
http
.
StatusOK
,
rr
.
Code
,
"status code should be 200"
)
// TODO make this type exist
var
withdrawalsResponse
WithdrawalsResponse
err
=
json
err
=
json
.
Unmarshal
(
rr
.
Body
.
Bytes
(),
&
withdrawalsResponse
)
assert
.
NoError
(
t
,
err
)
// Assert response data
assert
.
Equal
(
t
,
mockWithdrawals
,
withdrawalsResponse
.
Data
)
// Finally, assert that the methods were called with the expected parameters
mockDB
.
AssertCalled
(
t
,
"GetDeposits"
,
10
,
""
,
""
)
mockDB
.
AssertCalled
(
t
,
"GetWithdrawals"
,
10
,
""
,
""
,
""
)
}
indexer/go.mod
View file @
c725718c
...
...
@@ -5,8 +5,10 @@ go 1.19
replace github.com/ethereum/go-ethereum v1.11.4 => github.com/ethereum-optimism/op-geth v1.11.2-de8c5df46.0.20230321002540-11f0554a4313
require (
github.com/BurntSushi/toml v1.3.0
github.com/ethereum-optimism/optimism v0.2.1-0.20230326215719-b8e2fa58359a
github.com/ethereum/go-ethereum v1.11.4
github.com/go-chi/chi v1.5.4
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/lib/pq v1.10.4
...
...
@@ -17,7 +19,6 @@ require (
)
require (
github.com/BurntSushi/toml v1.3.0 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/VictoriaMetrics/fastcache v1.10.0 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
...
...
indexer/go.sum
View file @
c725718c
...
...
@@ -221,6 +221,8 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs=
github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
...
...
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