Skip to content

Commit

Permalink
Merge pull request #1 from coinbase/patrick/initial-commit
Browse files Browse the repository at this point in the history
Initial Commit
  • Loading branch information
patrick-ogrady authored Apr 1, 2020
2 parents f8b8aa6 + 82c1179 commit dafa60f
Show file tree
Hide file tree
Showing 84 changed files with 7,706 additions and 1 deletion.
26 changes: 26 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2020 Coinbase, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

version: 2
jobs:
build:
docker:
- image: circleci/golang:1.13
working_directory: /go/src/github.com/coinbase/rosetta-sdk-go
steps:
- checkout
- run: make deps
- run: make test
- run: make lint
- run: make check-license
19 changes: 19 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'bug'
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

**Expected behavior**
A clear and concise description of what you expected to happen.

**Additional context**
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'enhancement'
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.
16 changes: 16 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Fixes # .

### Motivation
<!--
Does this solve a bug? Enable a new use-case? Improve an existing behavior? Concrete examples are helpful here.
-->

### Solution
<!--
What is the solution here from a high level. What are the key technical decisions and why were they made?
-->

### Open questions
<!--
(optional) Any open questions or feedback on design desired?
-->
53 changes: 53 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Contributing to Rosetta-SDK-Go

## Code of Conduct

All interactions with this project follow our [Code of Conduct][code-of-conduct].
By participating, you are expected to honor this code. Violators can be banned
from further participation in this project, or potentially all Coinbase projects.

[code-of-conduct]: https://github.com/coinbase/code-of-conduct

## Bug Reports

* Ensure your issue [has not already been reported][1]. It may already be fixed!
* Include the steps you carried out to produce the problem.
* Include the behavior you observed along with the behavior you expected, and
why you expected it.
* Include any relevant stack traces or debugging output.

## Feature Requests

We welcome feedback with or without pull requests. If you have an idea for how
to improve the project, great! All we ask is that you take the time to write a
clear and concise explanation of what need you are trying to solve. If you have
thoughts on _how_ it can be solved, include those too!

The best way to see a feature added, however, is to submit a pull request.

## Pull Requests

* Before creating your pull request, it's usually worth asking if the code
you're planning on writing will actually be considered for merging. You can
do this by [opening an issue][1] and asking. It may also help give the
maintainers context for when the time comes to review your code.

* Ensure your [commit messages are well-written][2]. This can double as your
pull request message, so it pays to take the time to write a clear message.

* Add tests for your feature. You should be able to look at other tests for
examples. If you're unsure, don't hesitate to [open an issue][1] and ask!

* Submit your pull request!

## Support Requests

For security reasons, any communication referencing support tickets for Coinbase
products will be ignored. The request will have its content redacted and will
be locked to prevent further discussion.

All support requests must be made via [our support team][3].

[1]: https://github.com/coinbase/rosetta-sdk-go/issues
[2]: https://medium.com/brigade-engineering/the-secrets-to-great-commit-messages-106fc0a92a25
[3]: https://support.coinbase.com/customer/en/portal/articles/2288496-how-can-i-contact-coinbase-support-
2 changes: 1 addition & 1 deletion LICENSE → LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2020 Coinbase, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
33 changes: 33 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.PHONY: deps gen lint test add-license check-license circleci-local shellcheck salus
LICENCE_SCRIPT=addlicense -c "Coinbase, Inc." -l "apache" -v

deps:
go get ./...
go get github.com/stretchr/testify
go get github.com/davecgh/go-spew
go get golang.org/x/lint/golint
go get github.com/google/addlicense

gen:
./codegen.sh

lint:
golint -set_exit_status ./asserter/... ./fetcher/... ./gen/...

test:
go test -v ./asserter ./fetcher

add-license:
${LICENCE_SCRIPT} .

check-license:
${LICENCE_SCRIPT} -check .

circleci-local:
circleci local execute

shellcheck:
shellcheck codegen.sh

salus:
docker run --rm -t -v ${PWD}:/home/repo coinbase/salus
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# rosetta-sdk-go

[![Coinbase](https://circleci.com/gh/coinbase/rosetta-sdk-go/tree/master.svg?style=svg)](https://circleci.com/gh/coinbase/rosetta-sdk-go/tree/master)

## What is Rosetta?
Rosetta is a new project from Coinbase to standardize the process
of deploying and interacting with blockchains. With an explicit
specification to adhere to, all parties involved in blockchain
development can spend less time figuring out how to integrate
with each other and more time working on the novel advances that
will push the blockchain ecosystem forward. In practice, this means
that any blockchain project that implements the requirements outlined
in this specification will enable exchanges, block explorers,
and wallets to integrate with much less communication overhead
and network-specific work.

## Versioning
- Rosetta version: 1.2.4
- Package version: 0.0.1

## Installation

```shell
go get github.com/coinbase/rosetta-sdk-go
```

## Automatic Assertion
When using the helper methods to access a Rosetta Server (in `fetcher/*.go`),
responses from the server are automatically checked for adherence to
the Rosetta Interface. For example, if a `BlockIdentifer` is returned without a
`Hash`, the fetch will fail. Take a look at the tests in `asserter/*_test.go`
if you are curious about what exactly is asserted.

_It is possible, but not recommended, to bypass this assertion using the
`unsafe` helper methods available in `fetcher/*.go`._

## Development
* `make deps` to install dependencies
* `make gen` to generate models and helpers
* `make test` to run tests
* `make lint` to lint the source code (included generated code)

## License
This project is available open source under the terms of the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).

© 2020 Coinbase
110 changes: 110 additions & 0 deletions asserter/account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright 2020 Coinbase, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package asserter

import (
"fmt"
"reflect"

rosetta "github.com/coinbase/rosetta-sdk-go/gen"
)

// containsAccountIdentifier returns a boolean indicating if a
// *rosetta.AccountIdentifier is contained within a slice of
// *rosetta.AccountIdentifier. The check for equality takes
// into account everything within the rosetta.AccountIdentifier
// struct (including the SubAccountIdentifier).
func containsAccountIdentifier(
identifiers []*rosetta.AccountIdentifier,
identifier *rosetta.AccountIdentifier,
) bool {
for _, ident := range identifiers {
if reflect.DeepEqual(ident, identifier) {
return true
}
}

return false
}

// containsCurrency returns a boolean indicating if a
// *rosetta.Currency is contained within a slice of
// *rosetta.Currency. The check for equality takes
// into account everything within the rosetta.Currency
// struct (including currency.Metadata).
func containsCurrency(currencies []*rosetta.Currency, currency *rosetta.Currency) bool {
for _, curr := range currencies {
if reflect.DeepEqual(curr, currency) {
return true
}
}

return false
}

// assertBalanceAmounts returns an error if a slice
// of rosetta.Amount returned as an rosetta.AccountIdentifier's
// balance is invalid. It is considered invalid if the same
// currency is returned multiple times (these shoould be
// consolidated) or if a rosetta.Amount is considered invalid.
func assertBalanceAmounts(amounts []*rosetta.Amount) error {
currencies := make([]*rosetta.Currency, 0)
for _, amount := range amounts {
// Ensure a currency is used at most once in balance.Amounts
if containsCurrency(currencies, amount.Currency) {
return fmt.Errorf("currency %+v used in balance multiple times", amount.Currency)
}
currencies = append(currencies, amount.Currency)

if err := Amount(amount); err != nil {
return err
}
}

return nil
}

// AccountBalance returns an error if the provided
// rosetta.BlockIdentifier is invalid, if the same
// rosetta.AccountIdentifier appears in multiple
// rosetta.Balance structs (should be consolidated),
// or if a rosetta.Balance is considered invalid.
func AccountBalance(
block *rosetta.BlockIdentifier,
balances []*rosetta.Balance,
) error {
if err := BlockIdentifier(block); err != nil {
return err
}

accounts := make([]*rosetta.AccountIdentifier, 0)
for _, balance := range balances {
if err := AccountIdentifier(balance.AccountIdentifier); err != nil {
return err
}

// Ensure an account identifier is used at most once in a balance response
if containsAccountIdentifier(accounts, balance.AccountIdentifier) {
return fmt.Errorf("account identifier %+v used in balance multiple times", balance.AccountIdentifier)
}
accounts = append(accounts, balance.AccountIdentifier)

if err := assertBalanceAmounts(balance.Amounts); err != nil {
return err
}
}

return nil
}
Loading

0 comments on commit dafa60f

Please sign in to comment.