Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
- main

env:
TRIVY_VERSION: "v0.68.2"
TRIVY_VERSION: "v0.69.3"

jobs:
sec-scan:
Expand Down
218 changes: 134 additions & 84 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,119 +1,169 @@
# Dfns Golang SDK
# Dfns Go SDK

[![Go Build](https://github.com/dfns/dfns-sdk-go/actions/workflows/build.yaml/badge.svg)](https://github.com/dfns/dfns-sdk-go/actions/workflows/build.yaml)
[![Coverage](https://codecov.io/github/dfns/dfns-sdk-go/graph/badge.svg?token=0VPR2C7OZJ)](https://codecov.io/github/dfns/dfns-sdk-go)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/dfns/dfns-sdk-go/blob/master/LICENSE)
[![Godoc](https://godoc.org/github.com/dfns/dfns-sdk-go?status.svg)](https://godoc.org/github.com/dfns/dfns-sdk-go)
[![Go Report Card](https://goreportcard.com/badge/github.com/dfns/dfns-sdk-go)](https://goreportcard.com/report/github.com/dfns/dfns-sdk-go)

Welcome, builders 👋🔑 This repo holds Dfns Golang SDK. Useful links:

- [Dfns Website](https://www.dfns.co)
- [Dfns API Docs](https://docs.dfns.co)
Auto-generated Go SDK for the Dfns API.

## Installation

```
```bash
go get github.com/dfns/dfns-sdk-go
```

## Quick Start

## Concepts
```go
package main

### `CredentialSigner`

All state-changing requests made to the Dfns API need to be cryptographically signed by credentials registered with the User/Service Account.
import (
"context"
"fmt"
"log"

> **Note:** To be more precise, it's not the request itself that needs to be signed, but rather a "User Action Challenge" issued by Dfns. For simplicity, we refer to this process as "request signing".
dfns "github.com/dfns/dfns-sdk-go"
)

This request signature serves as cryptographic proof that only authorized entities are making the request. Without it, the request would result in an Unauthorized error.
func main() {
// Create the client (read-only operations)
dfnsClient, err := dfns.NewClient(dfns.Options{
AuthToken: "your-auth-token",
// BaseURL: "https://api.dfns.io", // Optional, this is the default
})
if err != nil {
log.Fatal(err)
}

// List wallets
ctx := context.Background()
wallets, err := dfnsClient.Wallets.ListWallets(ctx, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d wallets\n", len(wallets.Items))
}
```

Credentials currently support only Key Credentials (_refer to our [API documentation](https://docs.dfns.co/dfns-docs/getting-started/authentication-authorization#credentials) for more details_). Key Credentials are responsible for signing the challenge.
## User Action Signing

#### `AsymmetricKeySigner`
Some operations (like creating wallets or signing transactions) require user action signing.
Configure a signer to enable these operations:

This functionality is exposed in the `credential` repository. It is primarily intended for server-side use. Although it could be employed client-side, we don't recommend it. In a browser context, any key-based crypto signing should be handled within a service worker. We are actively working on additional helper classes to facilitate this support.
```go
package main

```golang
import (
.....
"github.com/dfns/dfns-sdk-go/credentials"
"context"
"log"
"os"

dfns "github.com/dfns/dfns-sdk-go"
"github.com/dfns/dfns-sdk-go/signer"
"github.com/dfns/dfns-sdk-go/wallets"
)

conf := &credentials.AsymmetricKeySignerConfig{
PrivateKey: os.Getenv("DFNS_PRIVATE_KEY"), // Credential private key
CredId: os.Getenv("DFNS_CRED_ID"), // Credential Id
}
func main() {
// Load your private key
privateKeyPEM, err := os.ReadFile("private_key.pem")
if err != nil {
log.Fatal(err)
}

// Create a signer (supports Ed25519, ECDSA, RSA keys)
keySigner, err := signer.NewKeySigner(
"cr-xxx-xxx", // Your credential ID
string(privateKeyPEM), // PEM-encoded private key
)
if err != nil {
log.Fatal(err)
}

// Create client with signer
dfnsClient, err := dfns.NewClient(dfns.Options{
AuthToken: "your-auth-token",
Signer: keySigner,
})
if err != nil {
log.Fatal(err)
}

// Operations requiring signatures will automatically sign
ctx := context.Background()
wallet, err := dfnsClient.Wallets.CreateWallet(ctx, wallets.CreateWalletRequest{
Network: "EthereumSepolia",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created wallet: %s\n", wallet.ID)
}
```

- `credential Id`: ID of the Credential registered with the auth token you’re using (Personal Access Token, or Service Account Token). In Dfns dashboard, you can find it next to your token (in `Settings` > `My Access Tokens` or `Settings > Service Accounts`)
- `Private Key`: private key (in .pem format) which only you have, associated with the public key you registered when you created your PAT / Service Account.

### `DfnsApiClient`
## Available Domains

`DfnsApiClient` is the main Dfns client, holding most supported functionalities of Dfns API.
The client provides access to the following API domains:

It needs to be authenticated, so `DfnsApiClient` needs to be passed a valid `authToken`. This `authToken` can be:
- `client.Auth` - Authentication and user management (53 endpoints)
- `client.Exchanges` - Exchange integrations (9 endpoints)
- `client.FeeSponsors` - Fee sponsor management (7 endpoints)
- `client.Keys` - Key management (12 endpoints)
- `client.Networks` - Network information (7 endpoints)
- `client.Permissions` - Permission management (8 endpoints)
- `client.Policies` - Policy management (8 endpoints)
- `client.Signers` - Signer management (2 endpoints)
- `client.Staking` - Staking operations (6 endpoints)
- `client.Wallets` - Wallet operations (31 endpoints)
- `client.Webhooks` - Webhook subscriptions (8 endpoints)
- `client.Swaps` - Token swap operations (5 endpoints)
- `client.Agreements` - Agreement management (2 endpoints)
- `client.Allocations` - Allocation management (5 endpoints)

- a Service Account token - _long-lived_
- a User Personal Access Token (PAT) - _long-lived_
- a User token issued after on User login - _expires_
Each domain provides typed methods for all available API endpoints.

`DfnsApiClient` also needs to be passed a [CredentialSigner](#credentialsigner), in order to sign requests.
## Error Handling

The `DfnsApiClient` provides a single function that creates a http client -> `CreateDfnsApiClient`
The http.Client returned will handle all the authentification process.
```go
package main

When the user performs a `POST, PUT or DELETE` using the client, it will automatically perform a `useraction` process (aka challenge signing).
If for a `POST, PUT or DELETE` endpoint, the `useraction` is not required, you should provide the header:

`x-dfns-useraction` to `false`. Doing that, it indicates the client to skip the challenge signing.

Please refer to the [Dfns API Docs](https://docs.dfns.co) to know which endpoints need a user action.

_Note: You can include a context directly in your httprequest if you want some control on shutdown logic_

```golang
import (
.....
api "github.com/dfns/dfns-sdk-go/dfnsapiclient"
"github.com/dfns/dfns-sdk-go/credentials"
"context"
"errors"
"fmt"
"log"

dfns "github.com/dfns/dfns-sdk-go"
)

signer := ... // a Credential Signer (webauthN or key signer from section above)

// Create a DfnsApiClient instance
apiOptions, err := api.NewDfnsBaseApiOptions(&api.DfnsBaseApiConfig{
OrgId: os.Getenv("DFNS_ORG_ID"), // ID of the Dfns Organisation
AuthToken: os.Getenv("DFNS_AUTH_TOKEN"), // an auth token
BaseUrl: os.Getenv("DFNS_API_URL"), // base Url of DFNS API
}, signer)
if err != nil {
fmt.Printf("Error creating DfnsApiOptions: %s", err)
return
func main() {
dfnsClient, err := dfns.NewClient(dfns.Options{
AuthToken: "your-auth-token",
})
if err != nil {
log.Fatal(err)
}

ctx := context.Background()
_, err = dfnsClient.Wallets.GetWallet(ctx, "invalid-wallet-id")
if err != nil {
var apiErr *dfns.APIError
if errors.As(err, &apiErr) {
fmt.Printf("API Error (status %d): %s\n", apiErr.StatusCode, apiErr.Body)
} else {
fmt.Printf("Error: %v\n", err)
}
}
}
```

dfnsClient := api.CreateDfnsApiClient(apiOptions)
## Supported Key Types

// Create wallet
walletData := struct {
Network string `json:"network"`
}{
Network: "EthereumGoerli",
}
The `KeySigner` supports the following private key types:

jsonData, err := json.Marshal(walletData)
if err != nil {
return fmt.Errorf("error marshaling JSON: %v", err)
}
| Algorithm | Description |
|-----------|-------------|
| Ed25519 | Edwards-curve Digital Signature Algorithm |
| ECDSA | Elliptic Curve DSA (P-256, secp256k1) |
| RSA | RSA PKCS#1 v1.5 with SHA-256 |

req, err := http.NewRequest("POST", apiOptions.BaseUrl+"/wallets", bytes.NewBuffer(jsonData))
if err != nil {
return fmt.Errorf("error creating POST request: %v", err)
}
Keys can be in PKCS#8, PKCS#1 (RSA), or SEC 1 (EC) PEM format.

response, err := dfnsClient.Do(req)
if err != nil {
return fmt.Errorf("error creating wallet: %v", err)
}
```
## License

MIT License - See LICENSE file for details.
50 changes: 50 additions & 0 deletions agreements/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions agreements/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading