Skip to content

Commit

Permalink
Merge pull request #9 from coinbase/main-1711664168
Browse files Browse the repository at this point in the history
v0.3.0 Release
  • Loading branch information
drohit-cb authored Mar 28, 2024
2 parents e22e893 + 2f57b8e commit e702cdd
Show file tree
Hide file tree
Showing 109 changed files with 11,384 additions and 9,589 deletions.
9 changes: 6 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# IDE/Tools
.docker
.idea
/.vscode
.vscode
# vim
.*.sw?

Expand All @@ -27,5 +27,8 @@ vendor/
# Cloud API key
.coinbase_cloud_api_key*.json

# Example binary
staking-client-*
# Example binaries
bin

# VSCode artifacts
**/__debug_bin**
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2018-2023 Coinbase, Inc.
Copyright (c) 2018-2024 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
305 changes: 249 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,263 @@
# Staking API Go Client Library
![Coinbase Staking API](docs/images/banner.svg)

This repository contains the Protocol Buffer definitions for the Coinbase **Staking API**, as well as the Go client libraries generated from them.
# [Coinbase Staking API](https://github.com/coinbase/staking-client-library-go)

> Programmatic access to Coinbase's best-in-class staking infrastructure and services. :large_blue_circle:
[![Current version](https://img.shields.io/github/tag/coinbase/staking-client-library-go?color=3498DB&label=version)](https://github.com/coinbase/staking-client-library-go/releases) [![GitHub contributors](https://img.shields.io/github/contributors/coinbase/staking-client-library-go?color=3498DB)](https://github.com/coinbase/staking-client-library-go/graphs/contributors) [![GitHub Stars](https://img.shields.io/github/stars/coinbase/staking-client-library-go.svg?color=3498DB)](https://github.com/coinbase/staking-client-library-go/stargazers) [![GitHub](https://img.shields.io/github/license/coinbase/staking-client-library-go?color=3498DB)](https://github.com/coinbase/staking-client-library-go/blob/main/LICENSE)

## Overview

Staking API provides a set of APIs to aid in non-custodial staking for multiple protocols and networks.
The **Coinbase Staking API** empowers developers to deliver a fully-featured staking experience in their Web2 apps, wallets, or dApps using *one common interface* across protocols.

# Documentation
A traditional infrastructure-heavy staking integration can take months. Coinbase's Staking API enables onboarding within hours by providing powerful and simple APIs on both sides of the staking experience.

In order to self-host the documentation run please use the swagger-ui docker container like so:
* [Orchestration](./protos/coinbase/staking/orchestration/v1): *Write*. Power non-custodial staking workflows for your users.

```bash
docker run -p 8080:8080 -e SWAGGER_JSON=/doc/coinbase/staking/v1alpha1/api.swagger.json -v $(PWD)/doc/openapi:/doc swaggerapi/swagger-ui
```
* [Rewards](./protos/coinbase/staking/rewards/v1): *Read*. Access onchain, staking-related rewards data.

## Quick Start

1. Create and download an API key from the [Cloud Platform](https://portal.cloud.coinbase.com/access/api).
2. Place the key named `.coinbase_cloud_api_key.json` at the root of this repository.
3. Run one of the code samples [below](#stake-partial-eth-💠) or any of our [provided examples](./examples/) :rocket:.

### Stake Partial ETH :diamond_shape_with_a_dot_inside:

This code sample creates an ETH staking workflow. View the full code sample [here](examples/ethereum/create-workflow/main.go)

<details open>
<summary>Code Sample</summary>

```golang
// examples/ethereum/create-workflow/main.go
package main

import (
"context"
"fmt"
"log"

## Prerequisites
"github.cbhq.net/cloud/staking-client-library-go/auth"
"github.cbhq.net/cloud/staking-client-library-go/client"
"github.cbhq.net/cloud/staking-client-library-go/client/options"
stakingpb "github.cbhq.net/cloud/staking-client-library-go/gen/go/coinbase/staking/orchestration/v1"
)

- [Golang 1.19+](https://go.dev/learn/)
func main() {
// TODO: Add your project ID found at cloud.coinbase.com or in your API key.
projectID := ""

## Repository Structure
- [`auth/`](./auth/) contains the authentication-related code for accessing Coinbase Cloud APIs.
- [`client/`](./client/) contains client instantiation helpers for Staking APIs.
- [`gen/`](./gen/) contains Go code generated from the Protocol Buffers.
- [`protos/`](./protos/) contains the Protocol Buffers that define the Staking APIs.
ctx := context.Background()

## Module Installation
// Loads the API key from the default location.
apiKey, err := auth.NewAPIKey(auth.WithLoadAPIKeyFromFile(true))
if err != nil {
log.Fatalf("error loading API key: %s", err.Error())
}

// Creates the Coinbase Staking API client.
stakingClient, err := client.New(ctx, options.WithAPIKey(apiKey))
if err != nil {
log.Fatalf("error instantiating staking client: %s", err.Error())
}

// Constructs the API request
req := &stakingpb.CreateWorkflowRequest{
Parent: fmt.Sprintf("projects/%s", projectID),
Workflow: &stakingpb.Workflow{
Action: "protocols/ethereum_kiln/networks/holesky/actions/stake",
StakingParameters: &stakingpb.Workflow_EthereumKilnStakingParameters{
EthereumKilnStakingParameters: &stakingpb.EthereumKilnStakingParameters{
Parameters: &stakingpb.EthereumKilnStakingParameters_StakeParameters{
StakeParameters: &stakingpb.EthereumKilnStakeParameters{
StakerAddress: "0xdb816889F2a7362EF242E5a717dfD5B38Ae849FE",
IntegratorContractAddress: "0xA55416de5DE61A0AC1aa8970a280E04388B1dE4b",
Amount: &stakingpb.Amount{
Value: "20",
Currency: "ETH",
},
},
},
},
},
SkipBroadcast: true,
},
}

workflow, err := stakingClient.Orchestration.CreateWorkflow(ctx, req)
if err != nil {
log.Fatalf("couldn't create workflow: %s", err.Error())
}

log.Printf("Workflow created: %s", workflow.Name)
}
```
go get github.com/coinbase/staking-client-library-go

</details>

<details>
<summary>Output</summary>

```text
2024/03/28 11:43:49 Workflow created: projects/62376b2f-3f24-42c9-9025-d576a3c06d6f/workflows/ffbf9b45-c57b-49cb-a4d5-fdab66d8cb25
```

</details>

### View Ethereum Rewards :moneybag:

This code sample returns rewards for an Ethereum validator address. View the full code sample [here](examples/ethereum/list-rewards/main.go).

<details open>
<summary>Code Sample</summary>

```golang
// examples/ethereum/list-rewards/main.go
package main

import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
"time"

"google.golang.org/api/iterator"

"github.cbhq.net/cloud/staking-client-library-go/auth"
"github.cbhq.net/cloud/staking-client-library-go/client"
"github.cbhq.net/cloud/staking-client-library-go/client/options"
rewardsV1 "github.cbhq.net/cloud/staking-client-library-go/client/rewards/v1"
rewardspb "github.cbhq.net/cloud/staking-client-library-go/gen/go/coinbase/staking/rewards/v1"
)

func main() {
ctx := context.Background()

// Loads the API key from the default location.
apiKey, err := auth.NewAPIKey(auth.WithLoadAPIKeyFromFile(true))
if err != nil {
log.Fatalf("error loading API key: %s", err.Error())
}

// Creates the Coinbase Staking API client.
stakingClient, err := client.New(ctx, options.WithAPIKey(apiKey))
if err != nil {
log.Fatalf("error instantiating staking client: %s", err.Error())
}

// Lists the rewards for the given address for the previous last 2 days, aggregated by day.
rewardsIter := stakingClient.Rewards.ListRewards(ctx, &rewardspb.ListRewardsRequest{
Parent: rewardspb.ProtocolResourceName{Protocol: "ethereum"}.String(),
PageSize: 200,
Filter: rewardsV1.WithAddress().Eq("0xac53512c39d0081ca4437c285305eb423f474e6153693c12fbba4a3df78bcaa3422b31d800c5bea71c1b017168a60474").
And(rewardsV1.WithPeriodEndTime().Gte(time.Now().AddDate(0, 0, -2))).
And(rewardsV1.WithPeriodEndTime().Lt(time.Now())).String(),
})

// Iterates through the rewards and print them.
for {
reward, err := rewardsIter.Next()
if errors.Is(err, iterator.Done) {
break
}

if err != nil {
log.Fatalf("error listing rewards: %s", err.Error())
}

marshaled, err := json.MarshalIndent(reward, "", " ")
if err != nil {
log.Fatalf("error marshaling reward: %s", err.Error())
}

fmt.Printf(string(marshaled))
}
}
```

## Get Started
To test that your API Key gives you access as expected to the Staking APIs:

1. Clone this GitHub repo
2. Download your API key from the Coinbase Cloud UI and save it as `.coinbase_cloud_api_key.json` at the root of this repo
3. Run `go run examples/example.go`
4. You should see output like the following:
```
2023/09/25 15:01:03 got protocol: protocols/ethereum_kiln
2023/09/25 15:01:04 got network: protocols/ethereum_kiln/networks/mainnet
2023/09/25 15:01:04 got action: protocols/ethereum_kiln/networks/goerli/actions/stake
2023/09/25 15:01:04 got action: protocols/ethereum_kiln/networks/goerli/actions/unstake
2023/09/25 15:01:04 got action: protocols/ethereum_kiln/networks/goerli/actions/claim_rewards
```
### Create an Ethereum Kiln workflow
To test creating an Ethereum Kiln workflow perform the following:
1. Open `examples/ethereum_kiln/example.go` and set the following variables:
* `projectID` - this is the project ID of your Coinbase Cloud project
* `privateKey` - this is the private key of the address with this you want to perform staking actions
* `stakerAddress` - this is the address with which you want to perform staking actions
* `integratorContractAddress` - this is the integrator contract address to which you want to stake. This is typically procured by engaging with the Coinbase Cloud sales team.
2. Run `go run examples/ethereum_kiln/example.go`
### Create a Polygon workflow
To test creating a Polygon workflow perform the following:
1. Open `examples/polygon/example.go` and set the following variables:
* `projectID` - this is the project ID of your Coinbase Cloud project
* `privateKey` - this is the private key of the address with this you want to perform staking actions
* `delegatorAddress` - this is the address with which you want to perform staking actions
2. Run `go run examples/polygon/example.go`
### Listing workflows
To test listing workflows within a project, perform the following:
1. Open `examples/example_list_workflows.go` and set the following variables:
* `projectID` - this is the project ID of your Coinbase Cloud project
2. Run `go run examples/example_list_workflows.go`
</details>

<details>
<summary>Output</summary>

```json
{
"address": "0xac53512c39d0081ca4437c285305eb423f474e6153693c12fbba4a3df78bcaa3422b31d800c5bea71c1b017168a60474",
"period_identifier": {
"date": "2024-03-26"
},
"aggregation_unit": 2,
"period_start_time": {
"seconds": 1711411200
},
"period_end_time": {
"seconds": 1711497599
},
"total_earned_native_unit": {
"amount": "0.00211503",
"exp": "18",
"ticker": "ETH",
"raw_numeric": "2115030000000000"
},
"total_earned_usd": [
{
"source": 1,
"conversion_time": {
"seconds": 1711498140
},
"amount": {
"amount": "7.58",
"exp": "2",
"ticker": "USD",
"raw_numeric": "758"
},
"conversion_price": "3582.979980"
}
],
"protocol": "ethereum"
}
{
"address": "0xac53512c39d0081ca4437c285305eb423f474e6153693c12fbba4a3df78bcaa3422b31d800c5bea71c1b017168a60474",
"period_identifier": {
"date": "2024-03-27"
},
"aggregation_unit": 2,
"period_start_time": {
"seconds": 1711497600
},
"period_end_time": {
"seconds": 1711583999
},
"total_earned_native_unit": {
"amount": "0.002034193",
"exp": "18",
"ticker": "ETH",
"raw_numeric": "2034193000000000"
},
"total_earned_usd": [
{
"source": 1,
"conversion_time": {
"seconds": 1711584540
},
"amount": {
"amount": "7.13",
"exp": "2",
"ticker": "USD",
"raw_numeric": "713"
},
"conversion_price": "3504.580078"
}
],
"protocol": "ethereum"
}
```

</details>

## Documentation

There are numerous examples in the [`examples directory`](./examples) to help get you started. For even more, refer to our [documentation website](https://docs.cloud.coinbase.com/) for detailed definitions, API specifications, integration guides, and more!
36 changes: 36 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package client

import (
"context"
"fmt"

"github.com/coinbase/staking-client-library-go/client/options"
orchestrationClient "github.com/coinbase/staking-client-library-go/client/orchestration/v1"
rewardsClient "github.com/coinbase/staking-client-library-go/client/rewards/v1"
)

type StakingClient struct {
Orchestration *orchestrationClient.OrchestrationServiceClient
Rewards *rewardsClient.RewardsServiceClient
}

// New returns a StakingClient based on the given inputs.
func New(
ctx context.Context,
stakingOpts ...options.StakingClientOption,
) (*StakingClient, error) {
orchestrationClient, err := orchestrationClient.NewOrchestrationServiceClient(ctx, stakingOpts...)
if err != nil {
return nil, fmt.Errorf("failed to create orchestration client: %w", err)
}

rewardsClient, err := rewardsClient.NewRewardsServiceClient(ctx, stakingOpts...)
if err != nil {
return nil, fmt.Errorf("failed to create rewards client: %w", err)
}

return &StakingClient{
Orchestration: orchestrationClient,
Rewards: rewardsClient,
}, nil
}
Loading

0 comments on commit e702cdd

Please sign in to comment.