Skip to content

Commit

Permalink
Merge branch 'master' into fe/adds-scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
abtestingalpha committed May 9, 2024
2 parents 3c10673 + db9440a commit e964466
Show file tree
Hide file tree
Showing 24 changed files with 1,011 additions and 51 deletions.
14 changes: 9 additions & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"eslint.workingDirectories": [
{ "directory": "packages/contracts", "changeProcessCWD": true }
{
"directory": "packages/contracts",
"changeProcessCWD": true
}
],
"eslint.nodePath": "./node_modules/eslint/bin/",
"eslint.format.enable": true,
"editorconfig.generateAuto": false,
"files.trimTrailingWhitespace": true,
"solidity.packageDefaultDependenciesContractsDirectory": "contracts",
"solidity.packageDefaultDependenciesDirectory": "lib",
"solidity.compileUsingRemoteVersion": "v0.8.17",
"solidity.formatter": "prettier"
}
"solidity.compileUsingRemoteVersion": "v0.8.17+commit.8df45f5f",
"solidity.formatter": "prettier",
"solidity.defaultCompiler": "remote"
}
93 changes: 93 additions & 0 deletions contrib/screener-api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,29 @@ package client

import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
"time"

"github.com/dubonzi/otelresty"
"github.com/go-resty/resty/v2"
"github.com/google/uuid"
"github.com/synapsecns/sanguine/core/ginhelper"
"github.com/synapsecns/sanguine/core/metrics"
)

var (
// BlacklistEndpoint is the endpoint for blacklisting an address.
BlacklistEndpoint = "/api/data/sync/"
)

// ScreenerClient is an interface for the Screener API.
type ScreenerClient interface {
ScreenAddress(ctx context.Context, ruleset, address string) (blocked bool, err error)
BlacklistAddress(ctx context.Context, appsecret string, appid string, body BlackListBody) (string, error)
}

type clientImpl struct {
Expand All @@ -37,6 +49,7 @@ type blockedResponse struct {
Blocked bool `json:"risk"`
}

// ScreenAddress checks if an address is blocked by the screener.
func (c clientImpl) ScreenAddress(ctx context.Context, ruleset, address string) (bool, error) {
var blockedRes blockedResponse
resp, err := c.rClient.R().
Expand All @@ -54,6 +67,54 @@ func (c clientImpl) ScreenAddress(ctx context.Context, ruleset, address string)
return blockedRes.Blocked, nil
}

// BlackListBody is the json payload that represents a blacklisted address.
type BlackListBody struct {
TypeReq string `json:"typereq"`
ID string `json:"id"`
Data string `json:"data"`
Address string `json:"address"`
Network string `json:"network"`
Tag string `json:"tag"`
Remark string `json:"remark"`
}

type blacklistResponse struct {
Status string `json:"status"`
Error string `json:"error"`
}

func (c clientImpl) BlacklistAddress(ctx context.Context, appsecret string, appid string, body BlackListBody) (string, error) {
var blacklistRes blacklistResponse

nonce := strings.ReplaceAll(uuid.New().String(), "-", "")[:32]
timestamp := fmt.Sprintf("%d", time.Now().Unix())
queryString := ""

signature := GenerateSignature(appsecret, appid, timestamp, nonce, queryString, body)

resp, err := c.rClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetHeader("appid", appid).
SetHeader("timestamp", timestamp).
SetHeader("nonce", nonce).
SetHeader("queryString", queryString).
SetHeader("signature", signature).
SetResult(&blacklistRes).
SetBody(body).
Post(BlacklistEndpoint)

if err != nil {
return resp.Status(), fmt.Errorf("error from server: %s: %w", resp.String(), err)
}

if resp.IsError() {
return resp.Status(), fmt.Errorf("error from server: %s", resp.String())
}

return blacklistRes.Status, nil
}

// NewNoOpClient creates a new no-op client for the Screener API.
// it returns false for every address.
func NewNoOpClient() (ScreenerClient, error) {
Expand All @@ -66,4 +127,36 @@ func (n noOpClient) ScreenAddress(_ context.Context, _, _ string) (bool, error)
return false, nil
}

func (n noOpClient) BlacklistAddress(_ context.Context, _ string, _ string, _ BlackListBody) (string, error) {
return "", nil
}

// GenerateSignature generates a signature for the request.
func GenerateSignature(secret string,
appid string,
timestamp string,
nonce string,
queryString string,
body BlackListBody,
) string {
key := []byte(secret)

// Concatenate the body.
message := fmt.Sprintf(
"%s%s%s%s%s%s%s",
appid,
timestamp,
nonce,
"POST",
BlacklistEndpoint,
queryString,
body,
)

h := hmac.New(sha256.New, key)
h.Write([]byte(message))

return strings.ToLower(hex.EncodeToString(h.Sum(nil)))
}

var _ ScreenerClient = noOpClient{}
4 changes: 4 additions & 0 deletions contrib/screener-api/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import "time"

// Config is the configuration for the screener.
type Config struct {
// AppSecret is the app secret
AppSecret string `yaml:"app-secret"`
// AppID is the app id
AppID string `yaml:"app-id"`
// TRMKey is the api key for trmlabs
TRMKey string `yaml:"trm-key"`
// Rules of [caller_type]->risk_type
Expand Down
27 changes: 26 additions & 1 deletion contrib/screener-api/db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,29 @@ package db
import (
"context"
"errors"
"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"time"

"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
)

// BlacklistedAddressWriterDB provides methods to write blacklisted addresses to the database.
type BlacklistedAddressWriterDB interface {
PutBlacklistedAddress(ctx context.Context, body BlacklistedAddress) error
DeleteBlacklistedAddress(ctx context.Context, id string) error
UpdateBlacklistedAddress(ctx context.Context, id string, body BlacklistedAddress) error
}

// BlacklistedAddressReaderDB provides methods to read blacklisted addresses from the database.
type BlacklistedAddressReaderDB interface {
GetBlacklistedAddress(ctx context.Context, address string) (*BlacklistedAddress, error)
}

// BlacklistedAddressDB is the interface for reading and writing blacklisted addresses to the database.
type BlacklistedAddressDB interface {
BlacklistedAddressWriterDB
BlacklistedAddressReaderDB
}

// RuleWriterDB is the interface for writing rules to the database.
type RuleWriterDB interface {
PutAddressIndicators(ctx context.Context, address string, riskIndicator []trmlabs.AddressRiskIndicator) error
Expand All @@ -24,5 +43,11 @@ type RuleDB interface {
RuleReaderDB
}

// DB is the general database interface for the screener-api.
type DB interface {
BlacklistedAddressDB
RuleDB
}

// ErrNoAddressNotCached is returned when an address is not cached.
var ErrNoAddressNotCached = errors.New("address not cached")
57 changes: 53 additions & 4 deletions contrib/screener-api/db/db_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package db_test

import (
"time"

"github.com/brianvoe/gofakeit/v6"
"github.com/synapsecns/sanguine/contrib/screener-api/db"
"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"time"
"gorm.io/gorm"
)

func (d *DBSuite) TestEmpty() {
d.RunOnAllDBs(func(testDB db.RuleDB) {
d.RunOnAllDBs(func(testDB db.DB) {
testAddress := gofakeit.BitcoinAddress()

// 5 mins ago
Expand All @@ -28,8 +30,8 @@ func (d *DBSuite) TestEmpty() {
})
}

func (d *DBSuite) TestAdressUpdate() {
d.RunOnAllDBs(func(testDB db.RuleDB) {
func (d *DBSuite) TestAddressUpdate() {
d.RunOnAllDBs(func(testDB db.DB) {
testAddress := gofakeit.BitcoinAddress()

// 5 mins ago
Expand Down Expand Up @@ -64,3 +66,50 @@ func (d *DBSuite) TestAdressUpdate() {
d.Require().Error(err, db.ErrNoAddressNotCached)
})
}

func (d *DBSuite) TestBlacklist() {
d.RunOnAllDBs(func(testDB db.DB) {
testAddress := gofakeit.BitcoinAddress()

blacklistBody := db.BlacklistedAddress{
TypeReq: "create",
ID: "testId",
Address: testAddress,
Network: "bitcoin",
Tag: "testTag",
Remark: "testRemark",
}

// blacklist the address
err := testDB.PutBlacklistedAddress(d.GetTestContext(), blacklistBody)
d.Require().NoError(err)
blacklistedAddress, err := testDB.GetBlacklistedAddress(d.GetTestContext(), blacklistBody.Address)
d.Require().NoError(err)
d.Require().NotNil(blacklistedAddress)

// update the address
blacklistBody.TypeReq = "update"
blacklistBody.Remark = "testRemarkUpdated"
err = testDB.UpdateBlacklistedAddress(d.GetTestContext(), blacklistBody.ID, blacklistBody)
d.Require().NoError(err)

// check to make sure it updated
blacklistedAddress, err = testDB.GetBlacklistedAddress(d.GetTestContext(), blacklistBody.Address)
d.Require().NoError(err)
d.Require().NotNil(blacklistedAddress)
d.Require().Equal("testRemarkUpdated", blacklistedAddress.Remark)

// check for non blacklisted address
res, err := testDB.GetBlacklistedAddress(d.GetTestContext(), gofakeit.BitcoinAddress())
d.Require().EqualError(err, gorm.ErrRecordNotFound.Error())
d.Require().Nil(res)

// delete it
err = testDB.DeleteBlacklistedAddress(d.GetTestContext(), blacklistBody.ID)
d.Require().NoError(err)

// delete nonexistent
err = testDB.DeleteBlacklistedAddress(d.GetTestContext(), "NonexistentId")
d.Require().NoError(err)
})
}
19 changes: 17 additions & 2 deletions contrib/screener-api/db/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,27 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"gorm.io/gorm/schema"
"strings"
"time"

"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"gorm.io/gorm/schema"
)

// BlacklistedAddress is a blacklisted address.
type BlacklistedAddress struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`

TypeReq string `gorm:"column:typereq" json:"typereq"`
ID string `gorm:"column:id;primary_key" json:"id"`
Data string `gorm:"column:data" json:"data"`
Address string `gorm:"column:address" json:"address"`
Network string `gorm:"column:network" json:"network"`
Tag string `gorm:"column:tag" json:"tag"`
Remark string `gorm:"column:remark" json:"remark"`
}

// AddressIndicators is the address indicators for a given address.
type AddressIndicators struct {
CreatedAt time.Time
Expand Down
Loading

0 comments on commit e964466

Please sign in to comment.