https://github.com/coinbase/staking-client-library-go
Programmatic access to Coinbase's best-in-class staking infrastructure and services. 🔵
https://github.com/coinbase/staking-client-library-go
rewards staking
Last synced: 4 months ago
JSON representation
Programmatic access to Coinbase's best-in-class staking infrastructure and services. 🔵
- Host: GitHub
- URL: https://github.com/coinbase/staking-client-library-go
- Owner: coinbase
- License: apache-2.0
- Created: 2023-07-15T03:24:47.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2025-04-01T15:22:59.000Z (6 months ago)
- Last Synced: 2025-05-09T20:07:36.636Z (5 months ago)
- Topics: rewards, staking
- Language: Go
- Homepage: https://github.com/coinbase/staking-client-library-go
- Size: 524 KB
- Stars: 22
- Watchers: 3
- Forks: 4
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# [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:
[](https://github.com/coinbase/staking-client-library-go/releases) [](https://github.com/coinbase/staking-client-library-go/graphs/contributors) [](https://github.com/coinbase/staking-client-library-go/stargazers) [](https://github.com/coinbase/staking-client-library-go/blob/main/LICENSE)
## Overview
`staking-client-library-go` is the Go SDK for the **Coinbase Staking API** :large_blue_circle:.
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.
A traditional infrastructure-heavy staking integration can take months. Coinbase's Staking API enables onboarding within hours :sparkles:.
## Quick Start
Prerequisite: [Go 1.21+](https://go.dev/doc/install)
1. In a fresh directory, copy and paste one of the code samples below or any of our [provided examples](./examples) into an `example.go` file.
2. Create a new API Key in the [portal](https://portal.cdp.coinbase.com/access/api) and paste the `apiKeyName` and `apiPrivateKey` into the `example.go` file.
3. Setup a Go project and run the example :rocket:
```shell
go mod init example
go mod tidy
go run example.go
```### Stake Partial ETH :diamond_shape_with_a_dot_inside:
This code sample helps stake ETH via partial staking. View the full source [here](examples/ethereum/create-workflow/main.go)
```golang
// examples/ethereum/create-workflow/main.go
package mainimport (
"context"
"fmt"
"log""google.golang.org/protobuf/encoding/protojson"
"github.com/coinbase/staking-client-library-go/auth"
"github.com/coinbase/staking-client-library-go/client"
"github.com/coinbase/staking-client-library-go/client/options"
api "github.com/coinbase/staking-client-library-go/gen/go/coinbase/staking/orchestration/v1"
)var (
apiKeyName = "your-api-key-name"
apiPrivateKey = "your-api-private-key"
)func main() {
ctx := context.Background()// Loads the API key.
apiKey, err := auth.NewAPIKey(auth.WithAPIKeyName(apiKeyName, apiPrivateKey))
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())
}req := &api.CreateWorkflowRequest{
Workflow: &api.Workflow{
Action: "protocols/ethereum_kiln/networks/holesky/actions/stake",
StakingParameters: &api.Workflow_EthereumKilnStakingParameters{
EthereumKilnStakingParameters: &api.EthereumKilnStakingParameters{
Parameters: &api.EthereumKilnStakingParameters_StakeParameters{
StakeParameters: &api.EthereumKilnStakeParameters{
StakerAddress: "0xdb816889F2a7362EF242E5a717dfD5B38Ae849FE",
Amount: &api.Amount{
Value: "20",
Currency: "ETH",
},
},
},
},
},
},
}workflow, err := stakingClient.Orchestration.CreateWorkflow(ctx, req)
if err != nil {
log.Fatalf("couldn't create workflow: %s", err.Error())
}marshaled, err := protojson.MarshalOptions{Indent: " ", Multiline: true}.Marshal(workflow)
if err != nil {
log.Fatalf("error marshaling reward: %s", err.Error())
}fmt.Println(string(marshaled))
}
```
Output```text
{
"name": "workflows/357673b5-c3b7-4149-a887-a6119d32fbdd",
"action": "protocols/ethereum_kiln/networks/holesky/actions/stake",
"ethereumKilnStakingParameters": {
"stakeParameters": {
"stakerAddress": "0xdb816889F2a7362EF242E5a717dfD5B38Ae849FE",
"integratorContractAddress": "0xA55416de5DE61A0AC1aa8970a280E04388B1dE4b",
"amount": {
"value": "20",
"currency": "ETH"
}
}
},
"state": "STATE_WAITING_FOR_EXT_BROADCAST",
"steps": [
{
"name": "stake tx",
"txStepOutput": {
"unsignedTx": "02f3824268068502540be4008503743b80ba83061a8094a55416de5de61a0ac1aa8970a280e04388b1de4b14843a4b66f1c0808080",
"state": "STATE_PENDING_EXT_BROADCAST"
}
}
],
"createTime": "2024-05-08T17:30:56.633391257Z",
"updateTime": "2024-05-08T17:30:56.633391257Z"
}
```
### Stake SOL :diamond_shape_with_a_dot_inside:
This code sample helps stake SOL from a given user wallet. View the full source [here](examples/solana/create-workflow/main.go)
```golang
// examples/solana/create-workflow/main.go
package mainimport (
"context"
"fmt"
"log""google.golang.org/protobuf/encoding/protojson"
"github.com/coinbase/staking-client-library-go/auth"
"github.com/coinbase/staking-client-library-go/client"
"github.com/coinbase/staking-client-library-go/client/options"
api "github.com/coinbase/staking-client-library-go/gen/go/coinbase/staking/orchestration/v1"
)var (
apiKeyName = "your-api-key-name"
apiPrivateKey = "your-api-private-key"
)func main() {
ctx := context.Background()// Loads the API key.
apiKey, err := auth.NewAPIKey(auth.WithAPIKeyName(apiKeyName, apiPrivateKey))
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())
}req := &api.CreateWorkflowRequest{
Workflow: &api.Workflow{
Action: "protocols/solana/networks/devnet/actions/stake",
StakingParameters: &api.Workflow_SolanaStakingParameters{
SolanaStakingParameters: &api.SolanaStakingParameters{
Parameters: &api.SolanaStakingParameters_StakeParameters{
StakeParameters: &api.SolanaStakeParameters{
WalletAddress: "8rMGARtkJY5QygP1mgvBFLsE9JrvXByARJiyNfcSE5Z",
Amount: &api.Amount{
Value: "100000000",
Currency: "SOL",
},
},
},
},
},
},
}workflow, err := stakingClient.Orchestration.CreateWorkflow(ctx, req)
if err != nil {
log.Fatalf("couldn't create workflow: %s", err.Error())
}marshaled, err := protojson.MarshalOptions{Indent: " ", Multiline: true}.Marshal(workflow)
if err != nil {
log.Fatalf("error marshaling reward: %s", err.Error())
}fmt.Println(string(marshaled))
}
```
Output```text
{
"name": "workflows/f68fc083-18bd-48a0-a10a-7c673e9ec5b7",
"action": "protocols/solana/networks/devnet/actions/stake",
"solanaStakingParameters": {
"stakeParameters": {
"walletAddress": "8rMGARtkJY5QygP1mgvBFLsE9JrvXByARJiyNfcSE5Z",
"validatorAddress": "GkqYQysEGmuL6V2AJoNnWZUz2ZBGWhzQXsJiXm2CLKAN",
"amount": {
"value": "100000000",
"currency": "SOL"
},
"priorityFee": {}
}
},
"state": "STATE_WAITING_FOR_EXT_BROADCAST",
"steps": [
{
"name": "stake tx",
"txStepOutput": {
"unsignedTx": "66hEYYWnwGWkGpMKF2H2sCzxnmoAfY8LPnYMgWdY6rC7hX2H6DEE2YdPxECFx8FeeNmea8N87L4KuZ6dirYXZi9XNr5uPJdf8W1jdShcSwzSmmqz4SA7dmFjdTM19hNEu7hMMF7C2RtjZj4qCRvArcnyjj76r5hJrm1o1RozjjZCyvgNqDGHYoeej9MPwoMUEaY6h2iKBh1hnkYFCA1tyXEP8xX3f1jbnae8jzW2Zkc62GDw2gKWusQ3KtRz3wRLdqWT9tbhEk6Hekqbw4sPXSPevsiYHPVX9mQJRdNkoYovBRXv3KQaQ7dv6isgyax7S53yoMRgCvfuhYxk9WhzR4fkAxYB26qeqpdUJrgvSpaw4T3iNBYsG7KZzvGUg4NWG1BaBDuvnG1x7YL3gyJd5QMWQ6jq6yuGgupjNn7zP7EcxtbvpP2EVfrFnzmX4LEgQh4MxshMFpNas2tQXQd12Vv9vq4nZt2BEr2Jh67Q9vnKF22td1XaAL1MvsTmvWWSKviyZkZQzTXsqUGFtox1f8Unwj75sNCQWYUh4PHmiUjWGmQVhyQKbEqG6PeqDyy9YTopamSD2ajDrhak5fsnczdXo166cjnzQAJZW7tN2T6jHJy2KNmDdL16qPR4HqKKXpWquf1NuTPuJ7ikfmJxWBp7gHrMF3z5P84hp4xT4V2D4eHGLMTWDhs4cQghVXRvynPUeUDSf3TWzHfYwVEDFNpFNhX62FP7aJBVp28R8nHTt7riymgkw9LdjhPMxQPoRW3hCG4UcQ9kJ7Aywcij9SVcbfaESoEz7anV1j6HFrXiQsgiSbeCj4iiXtYy9aDbVjiuv2v31kvoE6kb1s7osVoeK1mn7AxkPozMxTVhwca9BTMuHTYpFP1QTVAwsYSCXa6KuoXEgLKZn1c63ijQXXGENLjd17JqV3FK8x2Vurkunws8pAb",
"state": "STATE_PENDING_EXT_BROADCAST"
}
}
],
"createTime": "2024-05-08T17:33:40.843044346Z",
"updateTime": "2024-05-08T17:33:40.843044346Z"
}
```
### View Partial ETH Rewards :moneybag:
This code sample helps view rewards for an Ethereum wallet address. View the full source [here](examples/ethereum/list-rewards/partial-eth/main.go).
```golang
// examples/ethereum/list-rewards/partial-eth/main.go
package mainimport (
"context"
"errors"
"fmt"
"log"
"time""google.golang.org/api/iterator"
"google.golang.org/protobuf/encoding/protojson""github.com/coinbase/staking-client-library-go/auth"
"github.com/coinbase/staking-client-library-go/client"
"github.com/coinbase/staking-client-library-go/client/options"
"github.com/coinbase/staking-client-library-go/client/rewards"
filter "github.com/coinbase/staking-client-library-go/client/rewards/rewardsfilter"
api "github.com/coinbase/staking-client-library-go/gen/go/coinbase/staking/rewards/v1"
)const (
apiKeyName = "your-api-key-name"
apiPrivateKey = "your-api-private-key"address = "0x60c7e246344ae3856cf9abe3a2e258d495fc39e0"
)func main() {
ctx := context.Background()// Loads the API key.
apiKey, err := auth.NewAPIKey(auth.WithAPIKeyName(apiKeyName, apiPrivateKey))
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 May 1st, 2024 aggregated by day.
rewardsIter := stakingClient.Rewards.ListRewards(ctx, &api.ListRewardsRequest{
Parent: rewards.Ethereum,
PageSize: 200,
Filter: filter.WithAddress().Eq(address).
And(filter.WithPeriodEndTime().Gte(time.Date(2024, 5, 1, 0, 0, 0, 0, time.Local))).
And(filter.WithPeriodEndTime().Lt(time.Date(2024, 5, 2, 0, 0, 0, 0, time.Local))).String(),
})// Iterates through the rewards and pretty 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 := protojson.MarshalOptions{Indent: " ", Multiline: true}.Marshal(reward)
if err != nil {
log.Fatalf("error marshaling reward: %s", err.Error())
}fmt.Println(string(marshaled))
}
}
```
Output```json
{
"address": "0x60c7e246344ae3856cf9abe3a2e258d495fc39e0",
"date": "2024-05-01",
"aggregationUnit": "DAY",
"periodStartTime": "2024-05-01T00:00:00Z",
"periodEndTime": "2024-05-01T23:59:59Z",
"totalEarnedNativeUnit": {
"amount": "0.001212525541415161",
"exp": "18",
"ticker": "ETH",
"rawNumeric": "1212525541415161"
},
"totalEarnedUsd": [
{
"source": "COINBASE_EXCHANGE",
"conversionTime": "2024-05-02T00:09:00Z",
"amount": {
"amount": "3.61",
"exp": "2",
"ticker": "USD",
"rawNumeric": "361"
},
"conversionPrice": "2971.419922"
}
],
"endingBalance": null,
"protocol": "ethereum",
"rewardState": "PENDING_CLAIMABLE"
}
```
## 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.cdp.coinbase.com/staking/docs/welcome) for detailed definitions, [API specification](https://docs.cdp.coinbase.com/staking/reference), integration guides, and more!
## Contributing
Thanks for considering contributing to the project! Please refer to [our contribution guide](./CONTRIBUTING.md).
## Contact Us
If you have any questions, please reach out to us in the #staking channel on our [Discord](https://discord.com/invite/cdp) server.