diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 65ac10d..9881cd6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,3 +5,6 @@ # Published TypeScript SDK source, packaging, and release metadata. /packages/sdk-typescript/** @fuller @ximt + +# Published Go SDK source, module metadata, and release workflow. +/packages/sdk-go/** @fuller @ximt diff --git a/.github/workflows/release-go-sdk.yml b/.github/workflows/release-go-sdk.yml new file mode 100644 index 0000000..882f3b2 --- /dev/null +++ b/.github/workflows/release-go-sdk.yml @@ -0,0 +1,183 @@ +name: Release Go SDK + +on: + push: + tags: + - "packages/sdk-go/v*" + - "packages/sdk-go/websocket/gorilla/v*" + +permissions: + contents: read + +concurrency: + group: release-go-sdk-${{ github.ref_name }} + cancel-in-progress: false + +jobs: + minimum-go: + runs-on: ubuntu-24.04 + timeout-minutes: 15 + defaults: + run: + working-directory: packages/sdk-go + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version: "1.23.x" + cache: false + + - name: Test with minimum supported Go + env: + GOTOOLCHAIN: local + run: go test ./... + + release: + runs-on: ubuntu-24.04 + timeout-minutes: 45 + env: + # Do not allow an implicit toolchain download during a release. + GOTOOLCHAIN: local + defaults: + run: + working-directory: packages/sdk-go + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + persist-credentials: false + + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + # The generator module pins the minimum Go toolchain required by the + # vulnerability-fixed code generator; the SDK itself supports Go 1.23. + go-version-file: packages/sdk-go/scripts/go.mod + cache: true + cache-dependency-path: | + packages/sdk-go/go.mod + packages/sdk-go/go.sum + packages/sdk-go/websocket/gorilla/go.mod + packages/sdk-go/websocket/gorilla/go.sum + packages/sdk-go/scripts/go.mod + packages/sdk-go/scripts/go.sum + packages/sdk-go/cmd/demo/go.mod + packages/sdk-go/cmd/demo/go.sum + + - name: Verify release tag + id: release + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG_CREATED: ${{ github.event.created }} + RELEASE_TAG_FORCED: ${{ github.event.forced }} + run: | + set -euo pipefail + + tag="$GITHUB_REF_NAME" + test "$RELEASE_TAG_CREATED" = "true" + test "$RELEASE_TAG_FORCED" = "false" + + case "$tag" in + packages/sdk-go/v*) + module="github.com/gemini/developer-platform/packages/sdk-go" + ;; + packages/sdk-go/websocket/gorilla/v*) + module="github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla" + ;; + *) + echo "unsupported Go SDK release tag: $tag" >&2 + exit 1 + ;; + esac + + version="${tag##*/}" + if [[ ! "$version" =~ ^v(0|1)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then + echo "release tag must use a v0 or v1 semantic version: $tag" >&2 + exit 1 + fi + + # Release tags must be immutable annotated tags. GitHub's tag API + # verifies the signature using the repository's configured signing + # identities; lightweight or unverified tags cannot release. + test "$(git cat-file -t "$tag")" = "tag" + tag_object="$(git rev-parse "$tag^{tag}")" + if ! gh api "repos/${GITHUB_REPOSITORY}/git/tags/${tag_object}" \ + -H "X-GitHub-Api-Version: 2022-11-28" | \ + jq -e '.verification.verified == true and .verification.reason == "valid"' >/dev/null; then + echo "release tag signature is not verified by GitHub: $tag" >&2 + exit 1 + fi + + tagged_commit="$(git rev-parse "$tag^{commit}")" + test "$tagged_commit" = "$GITHUB_SHA" + + { + echo "module=$module" + echo "version=$version" + } >> "$GITHUB_OUTPUT" + + - name: Verify release commit is on main + run: git merge-base --is-ancestor "$GITHUB_SHA" origin/main + + - name: Verify module dependencies + run: | + set -euo pipefail + go mod verify + (cd websocket/gorilla && go mod verify) + (cd scripts && go mod verify) + (cd cmd/demo && go mod verify) + + - run: make test + - run: make race + - run: make vet + - name: Verify 32-bit wire integer decoding + run: GOARCH=386 go test ./generated/clearing + - run: make generate-check + - run: make release-smoke + + - name: Install pinned security analyzers + env: + GOBIN: ${{ runner.temp }}/go-bin + run: | + set -euo pipefail + # Use immutable module revisions rather than mutable release tags. + go install golang.org/x/vuln/cmd/govulncheck@d1f380186385b4f64e00313f31743df8e4b89a77 # v1.1.4 + go install github.com/securego/gosec/v2/cmd/gosec@c9453023c4e81ebdb6dde29e22d9cd5e2285fb16 # v2.22.8 + go install honnef.co/go/tools/cmd/staticcheck@b8ec13ce4d00445d75da053c47498e6f9ec5d7d6 # 2025.1.1 + echo "$GOBIN" >> "$GITHUB_PATH" + + - name: Run security analyzers + run: make security + + - name: Verify module is available from the public Go proxy + env: + SDK_MODULE: ${{ steps.release.outputs.module }} + SDK_VERSION: ${{ steps.release.outputs.version }} + run: | + set -euo pipefail + + # A newly pushed tag can take a short time to become visible through + # proxy.golang.org. Poll the proxy rather than silently falling back + # to a direct VCS fetch; this verifies the public consumer path. + for attempt in 1 2 3 4 5 6; do + if output="$( + GOPROXY=https://proxy.golang.org \ + GOSUMDB=sum.golang.org \ + GOTOOLCHAIN=local \ + go list -m "$SDK_MODULE@$SDK_VERSION" 2>&1 + )"; then + echo "$output" + exit 0 + fi + echo "Go proxy attempt $attempt failed: $output" >&2 + if [ "$attempt" -lt 6 ]; then + sleep 10 + fi + done + + echo "module was not available from proxy.golang.org: $SDK_MODULE@$SDK_VERSION" >&2 + exit 1 diff --git a/.github/workflows/validate-go-sdk.yml b/.github/workflows/validate-go-sdk.yml new file mode 100644 index 0000000..fffe0ba --- /dev/null +++ b/.github/workflows/validate-go-sdk.yml @@ -0,0 +1,90 @@ +name: Validate Go SDK + +on: + pull_request: + paths: + - "packages/sdk-go/**" + - ".github/workflows/validate-go-sdk.yml" + - ".github/workflows/release-go-sdk.yml" + +permissions: + contents: read + +jobs: + minimum-go: + runs-on: ubuntu-24.04 + timeout-minutes: 15 + defaults: + run: + working-directory: packages/sdk-go + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version: "1.23.x" + cache: false + + - name: Test with minimum supported Go + env: + GOTOOLCHAIN: local + run: go test ./... + + validate: + runs-on: ubuntu-24.04 + timeout-minutes: 45 + defaults: + run: + working-directory: packages/sdk-go + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + # The generator module pins the minimum Go toolchain required by the + # vulnerability-fixed code generator; the SDK itself supports Go 1.23. + go-version-file: packages/sdk-go/scripts/go.mod + cache: true + cache-dependency-path: | + packages/sdk-go/go.mod + packages/sdk-go/go.sum + packages/sdk-go/websocket/gorilla/go.mod + packages/sdk-go/websocket/gorilla/go.sum + packages/sdk-go/scripts/go.mod + packages/sdk-go/scripts/go.sum + packages/sdk-go/cmd/demo/go.mod + packages/sdk-go/cmd/demo/go.sum + + - name: Verify module dependencies + run: | + go mod verify + (cd websocket/gorilla && go mod verify) + (cd scripts && go mod verify) + (cd cmd/demo && go mod verify) + + - run: make test + - run: make race + - run: make vet + - name: Verify 32-bit wire integer decoding + run: GOARCH=386 go test ./generated/clearing + - run: make generate-check + - run: make release-smoke + + - name: Install pinned security analyzers + env: + GOBIN: ${{ runner.temp }}/go-bin + run: | + # Use immutable module revisions rather than mutable release tags. + go install golang.org/x/vuln/cmd/govulncheck@d1f380186385b4f64e00313f31743df8e4b89a77 # v1.1.4 + go install github.com/securego/gosec/v2/cmd/gosec@c9453023c4e81ebdb6dde29e22d9cd5e2285fb16 # v2.22.8 + go install honnef.co/go/tools/cmd/staticcheck@b8ec13ce4d00445d75da053c47498e6f9ec5d7d6 # 2025.1.1 + echo "$GOBIN" >> "$GITHUB_PATH" + + - name: Run security analyzers + run: make security diff --git a/README.md b/README.md index 6ffdead..f2d6826 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ A suite of developer tools for integrating with the [Gemini](https://www.gemini. | Package | Description | |---------|-------------| | [`packages/mcp-server`](packages/mcp-server/) | MCP server exposing Gemini API as tools for AI assistants | +| [`packages/sdk-go`](packages/sdk-go/) | Official Go SDK for the Gemini REST and WebSocket APIs | | [`samples/`](samples/) | REST and WebSocket examples in TypeScript, Python, and Go | | [`skills/`](skills/) | Claude Code skills (e.g., terminal candlestick charts) | diff --git a/packages/sdk-go/Makefile b/packages/sdk-go/Makefile new file mode 100644 index 0000000..ad25aaa --- /dev/null +++ b/packages/sdk-go/Makefile @@ -0,0 +1,57 @@ +.PHONY: all test race bench fuzz vet security fmt generate generate-check integration release-smoke + +all: fmt vet race bench + +test: + go test -v ./... + cd websocket/gorilla && go test -v ./... + cd scripts && go test -v ./... + cd cmd/demo && go test -v ./... + +race: + go test -race -v ./... + cd websocket/gorilla && go test -race -v ./... + cd scripts && go test -race -v ./... + cd cmd/demo && go test -race -v ./... + +bench: + go test -bench=. -benchmem ./websocket/orderbook + +fuzz: + go test -fuzz=FuzzHMAC_BuildPayload -fuzztime=5s ./auth + go test -fuzz=FuzzWebSocket_FrameParsing -fuzztime=5s ./websocket + +vet: + go vet ./... + cd websocket/gorilla && go vet ./... + cd scripts && go vet ./... + cd cmd/demo && go vet ./... + +security: + govulncheck ./... + # Nested modules are scanned explicitly below; excluding them here avoids + # treating their imports as packages in the parent module. + gosec -exclude-generated -exclude-dir=cmd/demo -exclude-dir=scripts -exclude-dir=websocket/gorilla ./... + staticcheck ./... + cd websocket/gorilla && govulncheck ./... && gosec -exclude-generated ./... && staticcheck ./... + cd scripts && govulncheck ./... && gosec -exclude-generated ./... && staticcheck ./... + cd cmd/demo && govulncheck ./... && gosec -exclude-generated ./... && staticcheck ./... + +fmt: + gofmt -s -w . + cd websocket/gorilla && gofmt -s -w . + cd scripts && gofmt -s -w . + cd cmd/demo && gofmt -s -w . + +generate: + cd scripts && go run generate.go + +generate-check: generate + git diff --exit-code generated/ + +integration: + @test -n "$$GEMINI_OAUTH_ACCESS_TOKEN" || (echo "GEMINI_OAUTH_ACCESS_TOKEN is required"; exit 1) + cd websocket/gorilla && go test -tags=integration ./... + +release-smoke: + bash ./scripts/release_smoke.sh diff --git a/packages/sdk-go/README.md b/packages/sdk-go/README.md new file mode 100644 index 0000000..59ff255 --- /dev/null +++ b/packages/sdk-go/README.md @@ -0,0 +1,828 @@ +# Gemini Go SDK + +Official Go library for the Gemini Exchange REST and WebSocket APIs. + +[![Go Version](https://img.shields.io/badge/go-1.23%2B-blue.svg)](https://golang.org) +[![Dependencies](https://img.shields.io/badge/core%20dependencies-zero-brightgreen.svg)](#installation) +[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) + +--- + +## Features + +- **Zero Core Dependencies**: The REST, authentication, decimal, and order-book packages use only the Go standard library. The optional Gorilla adapter is a separate module. +- **Predictable Concurrency**: Authenticated requests are nonce-serialized, WebSocket feeds apply backpressure, and order-book updates are atomic. +- **Accurate Financial Math**: Fixed-precision decimal arithmetic without floating-point errors. +- **Safe Retries**: Automatic backoff for idempotent requests with `Retry-After` header support. +- **Self-Healing WebSockets**: Automatic reconnection with exponential backoff and feed resumption. +- **Smart Quote Reconciler**: Preserves queue priority and minimizes exchange round-trips. +- **Secret Redaction**: Credentials never leak in `fmt.Printf`, `%#v`, `slog`, or JSON output. + +--- + +## Performance Benchmarks + +Benchmark numbers depend on the Go version, compiler, CPU, operating system, +and workload. Run the suite on the target environment instead of relying on +fixed measurements in documentation: + +```bash +go test -bench=. -benchmem ./... +``` + +The repository includes benchmarks for authentication, transport, decimal +arithmetic, WebSocket dispatch, and order-book operations. + +--- + +## Installation + +Install the core library: + +```bash +go get github.com/gemini/developer-platform/packages/sdk-go +``` + +Optional: Install the Gorilla WebSocket adapter: + +```bash +go get github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla +``` + +This repository is a monorepo, but `packages/sdk-go` is the published Go module +root. The `release-smoke` target stages the package as a standalone module and +compiles the documented import paths, generated packages, service facade, demo, +and optional Gorilla module. + +## Releases + +Go modules are published from Git tags; there is no package upload step. The +canonical module roots are: + +- `packages/sdk-go` → `github.com/gemini/developer-platform/packages/sdk-go` +- `packages/sdk-go/websocket/gorilla` → `github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla` + +The `scripts` and `cmd/demo` directories are repository-only modules and are +not released independently. Because these modules live below the repository +root, their Git tags must include the directory prefix required by Go's module +versioning rules. Consumers still use ordinary semantic versions: + +```bash +go get github.com/gemini/developer-platform/packages/sdk-go@v0.1.0 +go get github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla@v0.1.0 +``` + +After the release commit has been merged to `main`, a maintainer should create +signed, annotated tags on that commit and push only the module(s) being +released. The core module must be released before the Gorilla module when both +are being released, because the Gorilla module depends on the core module: + +```bash +git fetch origin main +release_commit="$(git rev-parse origin/main)" + +git tag -s packages/sdk-go/v0.1.0 \ + -m "sdk-go v0.1.0" "$release_commit" +git verify-tag packages/sdk-go/v0.1.0 +git push origin packages/sdk-go/v0.1.0 +``` + +After the core module's release workflow succeeds, release the optional +Gorilla module if it changed: + +```bash +git tag -s packages/sdk-go/websocket/gorilla/v0.1.0 \ + -m "sdk-go/websocket/gorilla v0.1.0" "$release_commit" +git verify-tag packages/sdk-go/websocket/gorilla/v0.1.0 +git push origin packages/sdk-go/websocket/gorilla/v0.1.0 +``` + +The [Go SDK release workflow](../../.github/workflows/release-go-sdk.yml) +accepts only new, signed annotated, v0/v1, and on-`main` tags. It runs the +complete test, race, vet, generation, standalone-consumer, and security +suites, and then verifies that the tagged module is available through +`proxy.golang.org`. Release tag rules in GitHub should also prevent tag +deletion or updates. Never move or reuse a published version tag; publish a +new semantic version for every release. A GitHub Release is optional and is +only for human-readable notes—the Git tag is the canonical Go release +artifact. + +Before the first release, repository administrators must protect both +`packages/sdk-go/v*` and `packages/sdk-go/websocket/gorilla/v*` tag patterns: +restrict tag creation to release maintainers and disallow updates and +deletion. The workflow has read-only GitHub permissions and never creates or +moves release tags. + +If a future major version requires `v2` or later, the module path must first +gain the corresponding `/v2` suffix and the release workflow and tag path must +be updated together, as required by Go's major-version module rules. + +To verify a release from the same public path used by consumers: + +```bash +GOPROXY=https://proxy.golang.org \ + go list -m github.com/gemini/developer-platform/packages/sdk-go@v0.1.0 +GOPROXY=https://proxy.golang.org \ + go list -m github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla@v0.1.0 +``` + +See Go's [module source management](https://go.dev/doc/modules/managing-source) +and [module publishing guide](https://go.dev/doc/modules/publishing) for the +underlying tag and proxy behavior. + +Use `Production` or `Sandbox` explicitly when selecting an environment. For +applications that must reject invalid configuration during startup, use the +error-returning constructor: + +```go +client, err := gemini.NewClientWithError( + gemini.WithEnvironment(gemini.Sandbox), +) +if err != nil { + log.Fatal(err) +} +defer client.Close() +``` + +Custom REST endpoints must use `https`; custom WebSocket endpoints must use the +`wss` scheme. Endpoints may include a path prefix but cannot include userinfo, +a query string, or a fragment. `NewClientWithError` validates both before +returning a client. The low-level HTTP transport also rejects every non-HTTPS +request, including public requests; use a TLS test server or in-memory +`RoundTripper` for isolated tests. + +--- + +## Authentication + +The library supports two authentication modes. + +### 1. API Keys (HMAC-SHA384) + +```go +client := gemini.NewClient( + gemini.WithAPIKey("your-api-key", "your-api-secret"), +) +``` + +`WithAPIKey` uses strictly increasing millisecond nonces for REST-only API-key +clients. If the same API key must authenticate private WebSocket traffic, it +must be a Gemini time-based key; configure it with +`gemini.WithTimeBasedAPIKey`, which uses epoch-second nonces on both surfaces. + +For startup validation, `NewClientWithError` rejects blank API keys or secrets +with `gemini.ErrInvalidHMACCredentials`. + +### 2. OAuth 2.0 Bearer Tokens + +Static token: + +```go +client := gemini.NewClient( + gemini.WithBearerToken("oauth-access-token"), +) +``` + +Dynamic token refresh with a `TokenSource`: + +```go +tokenSource := auth.TokenFunc(func(ctx context.Context) (string, error) { + return tokenManager.GetValidToken(ctx) +}) + +client := gemini.NewClient( + gemini.WithTokenSource(tokenSource), +) +``` + +The token source is application-owned. It must be safe for concurrent calls, +honor the request context, and return a current non-expired access token. The +SDK calls it for each authenticated HTTP attempt and each WebSocket connection +or reconnect; it does not force-refresh after a `401` response. The optional +`github.com/gemini/developer-platform/packages/sdk-go/oauth` package provides PKCE authorization-code +and refresh-token helpers without making interactive login part of the core +client. + +The OAuth package keeps token persistence application-owned. Its +`Config.Login` convenience uses a fixed loopback callback such as +`http://localhost:8787/callback`; that is the only HTTP URL permitted by the +package. Authorization and token endpoints must use HTTPS. Applications that +already have their own browser flow can use `Config.AuthCodeURL` and +`Config.Exchange` directly, then pass the result to `oauth.NewTokenSource`: + +```go +oauthConfig := oauth.Config{ + ClientID: os.Getenv("GEMINI_OAUTH_CLIENT_ID"), + Endpoint: oauth.Endpoint{ + AuthURL: "https://exchange.gemini.com/auth", + TokenURL: "https://exchange.gemini.com/auth/token", + }, + RedirectURL: "http://localhost:8787/callback", + Scopes: []string{"account:read", "orders:create"}, +} + +token, err := oauthConfig.Login(ctx, openBrowser) +if err != nil { + log.Fatal(err) +} +source, err := oauth.NewTokenSource(oauthConfig, *token) +if err != nil { + log.Fatal(err) +} +client := gemini.NewClient(gemini.WithTokenSource(source)) +``` + +`oauth.Source` refreshes once for concurrent callers, honors cancellation +while waiting for another refresh, and preserves a refresh token when the +provider omits it from a rotation response. It does not write credentials to +disk or a keychain; callers may load and persist tokens through their own +secure storage. +If a token source fails during an automatic WebSocket reconnect, the SDK stops +that reconnect loop, reports the underlying error through connection events, +and leaves the client disconnected so the source can be repaired before a +caller explicitly reconnects. + +For applications that need startup validation, `NewClientWithError` rejects a +nil or empty bearer configuration with `gemini.ErrInvalidTokenSource`. + +For private REST calls, the SDK encodes the request path and endpoint +parameters in Gemini's `X-GEMINI-PAYLOAD` header and sends no request body, as +required by Gemini OAuth. Callers only provide the generated request model. +Private REST methods fail locally with `gemini.ErrAuthenticationRequired` when +the client has no authentication strategy; no unauthenticated private request +is sent to the network. + +To revoke the active OAuth token, configure bearer authentication and call +`client.Account.RevokeOAuthToken(ctx)`. The endpoint revokes the token used by +that request; it is not available through API-key authentication. + +OAuth tokens can also authenticate private WebSocket streams and RFQ quote +methods. Gemini enforces the token's account capabilities server-side, so the +token must be authorized for the requested feed or operation. + +### OAuth Sandbox Integration Test + +An opt-in integration test validates one bearer REST request and one private +WebSocket handshake against the selected Gemini environment. It is skipped +when no token is supplied and never runs as part of the default test target: + +```bash +cd websocket/gorilla && \ +GEMINI_OAUTH_ACCESS_TOKEN="..." \ +GEMINI_OAUTH_ENVIRONMENT=sandbox \ +go test -tags=integration ./... +``` + +### Local OAuth and RFQ Demo + +The live demo uses the Markets CLI's public OAuth client ID by default, opens +the production consent page, and keeps the resulting tokens in memory only: + +```bash +cd cmd/demo +GEMINI_DEMO_OAUTH_LOGIN=1 go run . +``` + +To arm one live RFQ quote submission, also provide an explicit confirmation and +the quote parameters. The demo submits at most one quote, and only for an open +RFQ observed during its bounded window: + +```bash +GEMINI_DEMO_OAUTH_LOGIN=1 \ +GEMINI_DEMO_RFQ_SUBMIT=1 \ +GEMINI_DEMO_RFQ_CONFIRM=I_UNDERSTAND_THIS_SUBMITS_A_LIVE_RFQ_QUOTE \ +GEMINI_DEMO_RFQ_PRICE="0.55" \ +GEMINI_DEMO_RFQ_QUANTITY="100" \ +go run . +``` + +Use `GEMINI_OAUTH_CLIENT_ID` to override the default client ID and +`GEMINI_OAUTH_CLIENT_SECRET` only when the OAuth application requires one. +The loopback callback is HTTP on localhost by OAuth convention; all Gemini +authorization and token endpoints remain HTTPS. + +### 3. Webhook Signature Verification + +Verify incoming Gemini HMAC-SHA384 webhook signatures in constant time: + +```go +isValid := gemini.VerifySignature(secret, b64Payload, signatureHeader) +if !isValid { + http.Error(w, "invalid signature", http.StatusUnauthorized) + return +} +``` + +--- + +## Quick Start + +### Fetch Market Ticker + +```go +package main + +import ( + "context" + "fmt" + "log" + + "github.com/gemini/developer-platform/packages/sdk-go" +) + +func main() { + client := gemini.NewClient() + ctx := context.Background() + + ticker, err := client.MarketData.GetTicker(ctx, "BTCUSD") + if err != nil { + log.Fatalf("failed to fetch ticker: %v", err) + } + + fmt.Printf("BTC/USD Bid: %s, Ask: %s, Last: %s\n", gemini.Val(ticker.Bid), gemini.Val(ticker.Ask), gemini.Val(ticker.Last)) +} +``` + +--- + +### Place Orders + +Place maker post-only or limit orders with exact decimals: + +```go +amount := gemini.MustDecimal("0.05") +price := gemini.MustDecimal("65000.00") + +// Guaranteed Maker (Post-Only) +order, err := client.Trading.PostOnlyBid(ctx, "BTCUSD", amount, price) + +// Standard Limit Buy +order, err := client.Trading.LimitBuy(ctx, "BTCUSD", amount, price) + +// Immediate-or-Cancel Sell +order, err := client.Trading.ImmediateOrCancelSell(ctx, "BTCUSD", amount, price) +``` + +--- + +### Account Management, Staking, and Transfers + +```go +// Import the generated request models used by typed service methods: +// "github.com/gemini/developer-platform/packages/sdk-go/generated/account" + +// 1. Account balances and subaccounts +balances, err := client.Account.GetBalances(ctx, &account.GetAvailableBalancesJSONBody{Account: "primary"}) +accounts, err := client.Account.ListAccounts(ctx, nil) + +// 2. Staking lifecycle (provider ID is required by the API) +stkBalances, err := client.Staking.GetStakingBalances(ctx, nil) +stakeTx, err := client.Staking.Stake(ctx, &account.StakeCryptoFundsJSONBody{ProviderId: "provider-id", Currency: "ETH", Amount: "1.5"}) +unstakeRes, err := client.Staking.Unstake(ctx, &account.UnstakeCryptoFundsJSONBody{ProviderId: "provider-id", Currency: "ETH", Amount: "0.5"}) + +// 3. Multichain transfers and fee estimates +feeEst, err := client.Transfers.GetWithdrawalFeeEstimateV2(ctx, "solana", "sol", "address", "10.0") +withdrawRes, err := client.Transfers.WithdrawCryptoV2(ctx, "solana", "sol", "address", "10.0") +// Pass a generated *account.ListPastTransfersJSONBody for typed filters; +// nil requests the endpoint defaults. +pastTransfers, err := client.Transfers.GetTransfers(ctx, nil) +``` + +--- + +### Declarative Quote Reconciler + +Synchronize a market-making ladder. The reconciler diffs your desired orders against open orders, keeps matching orders in the exchange queue, and sends only required cancels and new orders: + +```go +// Create reconciler with a 0.5 bps tolerance band +reconciler := client.NewQuoteReconciler("BTCUSD", + gemini.WithToleranceBps(0.5), + gemini.WithQuantization(gemini.MustDecimal("0.01"), gemini.MustDecimal("0.0001")), +) + +// StartStreaming subscribes before the initial REST hydration and replays +// order events received during that handoff. +errChan, err := reconciler.StartStreaming(ctx) +if err != nil { + log.Fatalf("stream error: %v", err) +} + +// Define target quotes and sync +mid := gemini.MustDecimal("65000") +size := gemini.MustDecimal("0.05") +desired := []gemini.DesiredQuote{ + {Side: "buy", Price: mid.SubBps(5.0), Amount: size}, + {Side: "sell", Price: mid.AddBps(5.0), Amount: size}, +} + +result, err := reconciler.Sync(ctx, desired) +if err != nil { + log.Fatalf("reconciliation could not start: %v", err) +} +if err := result.Err(); err != nil { + log.Printf("reconciliation completed with partial failures: %v", err) +} +log.Printf("Sync: Kept=%d, Cancelled=%d, Placed=%d", + result.Kept, result.Cancelled, result.Placed) +``` + +Each reconciler supports one active stream; cancel its context before starting +another stream. Reconciler cleanup removes only its own WebSocket order-event +subscription, so other subscribers on the same private WebSocket remain active. + +--- + +### REST service surface + +The `generated` packages are regenerated from Gemini's deployed REST contracts +and contain request and response models for every documented REST operation. +The hand-written `services` facade intentionally exposes a smaller, curated +set of core trading, market-data, account, transfer, staking, margin, +perpetuals, clearing, and prediction-market operations. The supported subset +is tracked by an operation-to-method coverage test in `scripts/`; a spec change +cannot silently add an unclassified endpoint. + +For operations not yet surfaced by a high-level service, use the generated +models with `transport.Client.Request` or wait for a typed service method. The +prediction-market facade includes typed batch order/cancel, order history, +positions, settled positions, combos, volume metrics, maker-rebate, and +liquidity-rewards operations. Native Go iterators are available for the +paginated event, order, position, combo, and liquidity-rewards collections. +Some less common REST and clearing/reporting operations remain available through +the generated models and transport client. + +Prediction-market event responses preserve the complete sports metadata model: +`Event.SportsMarket` includes sport, market type, subject, scope, and metric, +and `PredictionsService.GetEvents` accepts all corresponding repeated filters. +For higher-level sports discovery, `services.ClusterSportsEvents` groups raw +events by contest root and `services.ResolveSportsContest` resolves a contest +from an already-fetched event set without adding network behavior to the REST +client. + +--- + +### Public and Private WebSocket Connections + +The SDK keeps public and private WebSocket traffic on separate client +instances and separate connections: + +- `client.PublicWebSocket()` is unauthenticated and is for public market data + such as depth, trades, book ticker, and contract status. +- `client.PrivateWebSocket()` is the authenticated connection for order, + balance, position, and settlement feeds. Configure `WithAPIKey`, + `WithTimeBasedAPIKey`, `WithBearerToken`, or another auth option first. + `WithAPIKey` uses strict-increasing REST nonces and is intended for + REST-only API-key clients; use `WithTimeBasedAPIKey` when the same key must + authenticate both REST and private WebSocket traffic. + +```go +client := gemini.NewClient( + gemini.WithEnvironment(gemini.Sandbox), + gemini.WithTimeBasedAPIKey("your-api-key", "your-api-secret"), +) +defer client.Close() + +publicWS := client.PublicWebSocket() +depth, err := publicWS.SubscribeDepth(ctx, "BTCUSD") +if err != nil { + log.Fatal(err) +} + +privateWS := client.PrivateWebSocket() +orders, err := privateWS.SubscribeOrderEvents(ctx) +if err != nil { + log.Fatal(err) +} + +// UnsubscribeOrderEvents removes every order-event subscriber. To remove only +// this subscriber, use UnsubscribeOrderEventsChannel(ctx, orders). + +go func() { + for update := range depth { + log.Printf("public depth update: %d", update.LastUpdateID) + } +}() +go func() { + for update := range orders { + log.Printf("private order %d: %s", update.OrderID, update.OrderStatus) + } +}() +``` + +Typed stream options mirror the supported AsyncAPI variants. Use +`SubscribeDepthWithOptions` for the 100ms differential stream, +`SubscribePartialDepth` with `DepthLevel5`, `DepthLevel10`, or `DepthLevel20` +for top-of-book snapshots, `SubscribeOrderEventsWithScope` for account versus +session orders, and `SubscribeBalancesWithOptions` or +`SubscribePositionsWithOptions` with `Interval: time.Second` for throttled +snapshots. Settlements currently have only the documented account stream; +the SDK does not invent a session variant that is absent from the spec. + +The WebSocket control plane and authenticated order methods are typed as well: +use `ConnInfo`, `Time`, `ListSubscriptions`, `SubscribeStreams`, and +`UnsubscribeStreams` for protocol control requests, and `PlaceOrder`, +`CancelOrder`, `CancelAllOrders`, and `CancelSessionOrders` for trading +requests. Raw `SubscribeStreams` calls are direct protocol operations and are +not replayed automatically after reconnect; private stream names fail closed +on a public client. Use `RequestAuthenticated` for dynamically named private +methods, and use the typed feed subscription methods when feed resumption is +required. `PlaceOrder` accepts `LIMIT` and `MARKET`. A stop-limit order uses +`Type: "LIMIT"` with both `Price` and `StopPrice`; Gemini reports the resulting +order as `STOP_LIMIT` on the order-event stream. `stopPrice` is not valid with +`MARKET`. The WebSocket contract allows `stopPrice == Price`; the legacy REST +`TradingService.NewOrder` contract requires a strict inequality (`stopPrice < +Price` for buys and `stopPrice > Price` for sells). Account-wide cancellation requires +`CancelAllOptions{Confirm: true}` over WebSocket or +`CancelAllOrdersOptions{Confirm: true}` through `TradingService` so a +destructive request cannot be issued by omitting a parameter accidentally. + +Partial-depth subscriptions use one underlying connection per symbol because +their snapshot envelope may not include a symbol. Differential depth +subscriptions remain multiplexed because their snapshots include the market +symbol. The root SDK configures this behavior automatically. Low-level clients +that need the same behavior can use +`websocket.WithIsolatedPartialSnapshots()`; the older +`websocket.WithIsolatedSnapshots()` remains available when both feed types +must be isolated. + +An unauthenticated client still exposes `PrivateWebSocket()` so applications +can construct clients uniformly, but private subscriptions fail immediately +with `gemini.ErrAuthenticationRequired`; no unauthenticated connection is +silently upgraded or reused. The low-level `websocket.NewPublicClient` and +`websocket.NewPrivateClient` constructors provide the same separation when the +root `gemini.Client` facade is not used. + +The Go SDK exposes the public `requestForQuote` discovery stream, authenticated +`requestForQuote@account`/`@session` delivery streams, and typed +`SubmitRFQQuote`, `WithdrawRFQQuote`, and `ConfirmRFQQuote` methods. RFQ +deliveries are at-least-once; deduplicate them by `DeliveryID` before applying +lifecycle transitions. Quote methods require an authenticated WebSocket +client and preserve the API's explicit `Confirm` boolean—no action is taken on +the caller's behalf. Each `RFQLeg` includes its contract ID and outcome, plus +the optional leg-specific `InstrumentSymbol`; this is distinct from the +combo-level `RFQPublicEvent.Symbol`. + +```go +rfqs, err := client.PublicWebSocket().SubscribeRFQEvents(ctx) +if err != nil { + return err +} +for rfq := range rfqs { + if rfq.State != websocket.RFQStateOpen { + continue + } + // Insert application-specific pricing here. The SDK does not choose a + // price or submit a quote automatically. + quote, err := client.PrivateWebSocket().SubmitRFQQuote(ctx, websocket.RFQSubmitQuoteParams{ + RFQID: rfq.RFQID, Price: "0.55", Quantity: "100", + }) + if err != nil { + return err + } + _ = quote.QuoteID +} +``` + +The public and private WebSocket clients are intentionally separate. Use the +private client for RFQ quote methods and authenticated delivery streams; it +must be created with the same account credentials used for the relevant +capabilities. + +Inbound WebSocket messages are limited to 1 MiB by default. Configure a +different limit with `websocket.WithMaxMessageSize`, or pass a non-positive +value only when the transport is trusted and an unbounded payload is required. +Malformed JSON frames are reported through `ConnectionEvent.Err` as +`websocket.ErrMalformedFrame`; the connection remains alive so callers can +continue receiving valid frames. For unattended processes, opt into +application-level liveness checks with +`websocket.WithLiveness(interval, timeout)`. A failed check is reported as +`websocket.ErrLivenessFailed` and follows the normal reconnect policy. + +### Real-Time Order Book and BBO Callbacks + +This example uses the optional `github.com/gemini/developer-platform/packages/sdk-go/websocket/orderbook` +package. Always drain subscription channels; the client applies backpressure +to preserve every update. Feed channels are bounded. If a consumer falls +behind far enough to fill the client's inbound dispatch queue, the client +reports `websocket.ErrSlowConsumer` through its lifecycle event channel and +reconnects when automatic reconnect is enabled. Treat that event as a data +recovery boundary: rebuild order-book state from a snapshot and reconcile +private order state with REST before continuing. + +```go +liveBook := orderbook.NewLiveOrderBook("BTCUSD") + +// Book returns a read-only view. Apply snapshots and diffs through liveBook +// so sequence and recovery state remains synchronized. +bookView := liveBook.Book() +_ = bookView.LastUpdateID() + +// Callback triggers only when the Top-of-Book changes +liveBook.OnBBOChanged(func(bbo orderbook.BBO) { + fmt.Printf("Bid: %s | Ask: %s | Mid: %.2f | Spread: %.2f bps\n", + bbo.BestBid, bbo.BestAsk, bbo.Mid, bbo.SpreadBps) +}) + +depthStream, err := client.PublicWebSocket().SubscribeDepth(ctx, "BTCUSD") +if err != nil { + log.Fatalf("subscribe error: %v", err) +} + +for diff := range depthStream { + if err := liveBook.IngestDiff(diff); err != nil { + log.Printf("Sequence gap detected, resyncing: %v", err) + break + } +} +``` + +The top-level SDK requests a full order-book snapshot when it connects the +public WebSocket. The first snapshot frame is marked internally and can be +passed directly to `IngestDiff`; subsequent frames are differential updates. +The live book intentionally does not infer snapshot state from `U == u`, since +that is also valid for a normal differential update. If you construct a +low-level WebSocket client directly, opt into the same behavior with +`websocket.WithSnapshot(-1)`. + +### Prediction Market Terms + +Prediction-market orders are sent to Gemini immediately. If the backend +returns `gemini.ErrAcceptTermsRequired`, explicitly call +`client.Predictions.AcceptTerms(ctx)` and retry the order. The SDK never checks +terms in advance or accepts them on the caller's behalf. + +--- + +### Concurrency and Recovery Guarantees + +- Private REST requests using HMAC authentication are serialized per client so + retries cannot send a lower nonce after a later request. +- Call `client.Close()` when the SDK client is no longer needed to stop WebSocket + pumps and release idle connections from the SDK-owned HTTP transport. A + caller-provided `WithHTTPClient` remains caller-owned. +- WebSocket `Request` and `Ping` calls wait for their correlated server response; + subscription methods return protocol errors instead of treating a write as + success. Use `errors.Is(err, websocket.ErrRequestFailed)` to classify a + rejected request. +- WebSocket lifecycle events are buffered and coalesced if the consumer falls + behind; use `State()` as the authoritative current state. +- WebSocket subscription channels are flow-controlled. If a consumer fills the + bounded inbound queue, the client closes feed channels and emits + `websocket.ErrSlowConsumer`; applications must resync state before + subscribing again. +- Order-book snapshots and diffs reject malformed or negative levels without + partially mutating the book. Sequence gaps return `gemini.ErrResyncRequired`. +- `LiveOrderBook.Reset` clears both sequence state and price levels. Call it + before applying a fresh snapshot after a disconnect or sequence gap. + +--- + +### Validation + +From this directory, the package checks are: + +```bash +gofmt -l . +go test ./... +go test -race ./... +go vet ./... +``` + +The `scripts` module fetches the allowlisted deployed OpenAPI/AsyncAPI contracts, +verifies their SHA-256 hashes, and contains contract-drift tests: + +```bash +(cd scripts && go test ./...) +``` + +--- + +### Managed Heartbeat (Dead-Man's Switch) + +Keep an active trading session alive in the background: + +```go +session := client.Heartbeat.Start(ctx, 5*time.Second) +defer session.Stop() + +go func() { + for err := range session.Errors() { + log.Printf("Heartbeat error: %v", err) + } +}() +``` + +--- + +### Fixed-Precision Decimals and Basis Points Math + +`types.Decimal` preserves the quoted-string representation used by string +decimal fields. Generated models for OpenAPI numeric decimal fields use +`types.DecimalNumber`, which accepts either quoted or numeric input but emits +an exact JSON number without converting through `float64`. + +```go +price := gemini.MustDecimal("65000.00") + +// Add and subtract basis points +ask := price.AddBps(10.0) // 65065.00 +bid := price.SubBps(10.0) // 64935.00 + +// Measure difference in basis points +diffBps := ask.BpsDiff(bid) // 20.0 bps + +// Quantize to market tick and lot rules +tickSize := gemini.MustDecimal("0.50") +lotSize := gemini.MustDecimal("0.001") + +quantizedPrice := gemini.MustDecimal("65000.37").QuantizePrice(tickSize) // 65000.00 +quantizedQty := gemini.MustDecimal("0.1237").QuantizeAmount(lotSize) // 0.123 +``` + +--- + +### Error Handling + +All errors returned by the SDK seamlessly unwrap to typed sentinels. You can inspect errors using standard `errors.Is()` or the top-level helper functions in a single flat `switch`: + +#### 1. Flat Top-Level Error Inspection (Recommended) + +```go +order, err := client.Trading.PostOnlyBid(ctx, "BTCUSD", amount, price) +if err != nil { + // Optional: Extract request ID for Gemini Support logs + if reqID := gemini.RequestIDFromError(err); reqID != "" { + log.Printf("Gemini Request ID: %s", reqID) + } + + switch { + case gemini.IsInsufficientFunds(err): + log.Println("Domain: Insufficient balance to place order") + + case gemini.IsMarketClosed(err): + log.Println("Domain: Market or trading pair is halted") + + case gemini.IsRateLimit(err): + log.Println("API: Rate limit exceeded (automatic backoff engaged)") + + case gemini.IsSelfCrossPrevented(err): + log.Println("Domain: Self-trade prevention triggered") + + case gemini.IsAuthError(err): + log.Fatalf("Auth: Invalid keys, signature, or nonce") + + case gemini.IsNotFound(err): + log.Println("API: Order or symbol not found") + + case gemini.IsResyncRequired(err): + log.Println("Stream: Sequence gap detected; resyncing book...") + + default: + log.Printf("Unhandled error: %v", err) + } +} +``` + +#### 2. Broad Category Inspection (For Middleware, Routing, & Alerting) + +```go +switch { +case gemini.IsDomainError(err): + // Exchange matching engine business rejections (do not retry) + log.Printf("Business logic rejection: %v", err) + +case gemini.IsAPIError(err): + // Gateway / HTTP 4xx / 5xx responses + if apiErr, ok := gemini.AsAPIError(err); ok { + log.Printf("HTTP %d (%s): %s", apiErr.StatusCode, apiErr.Reason, apiErr.Message) + } + +case gemini.IsTimeout(err): + // Client-side deadline exceeded + log.Println("Request timed out") +} +``` + +--- + +### Testing with `geminitest` + +Use the local mock server for testing without network requests: + +```go +server := geminitest.NewMockServer("test-key", "test-secret") +defer server.Close() + +client := gemini.NewClient( + gemini.WithCustomRESTURL(server.URL()), + gemini.WithAPIKey("test-key", "test-secret"), +) +``` + +--- + +## License + +Apache 2.0. See the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0) +for details. diff --git a/packages/sdk-go/aliases.go b/packages/sdk-go/aliases.go new file mode 100644 index 0000000..f262271 --- /dev/null +++ b/packages/sdk-go/aliases.go @@ -0,0 +1,223 @@ +package gemini + +import ( + "context" + "iter" + + "github.com/gemini/developer-platform/packages/sdk-go/auth" + "github.com/gemini/developer-platform/packages/sdk-go/services" + "github.com/gemini/developer-platform/packages/sdk-go/transport" + "github.com/gemini/developer-platform/packages/sdk-go/types" + "github.com/gemini/developer-platform/packages/sdk-go/websocket" + "github.com/gemini/developer-platform/packages/sdk-go/websocket/orderbook" +) + +// Re-exported types for streamlined developer experience without importing multiple sub-packages. +type ( + // APIKey represents a Gemini API Key identifier. + APIKey = auth.APIKey + + // APISecret represents a Gemini API secret used for HMAC-SHA384 signatures. + APISecret = auth.APISecret + + // BearerToken represents an OAuth2 bearer access token. + BearerToken = auth.BearerToken + + // Decimal represents an exact fixed-precision decimal number for financial calculations. + Decimal = types.Decimal + + // DecimalNumber represents an exact decimal encoded as a JSON number. + DecimalNumber = types.DecimalNumber + + // DesiredQuote specifies an intended target order in a market making grid. + DesiredQuote = services.DesiredQuote + + // RestingOrder represents an active order resting on the exchange order book. + RestingOrder = services.RestingOrder + + // ReconcileResult summarizes actions executed by the state reconciler. + ReconcileResult = services.ReconcileResult + + // CustodyFeeTransfer describes a custody fee charged to the account. + CustodyFeeTransfer = services.CustodyFeeTransfer + + // AddBankResponse is returned when a bank account is submitted for linking. + AddBankResponse = services.AddBankResponse + + // ApprovedAddressMessage is returned when an approved address is requested or removed. + ApprovedAddressMessage = services.ApprovedAddressMessage + + // PaymentMethodsResponse contains linked account payment methods. + PaymentMethodsResponse = services.PaymentMethodsResponse + + // ClearingOperationResponse reports a clearing cancellation or confirmation result. + ClearingOperationResponse = services.ClearingOperationResponse + + // PredictionOrderOperationResponse reports a prediction-market order action result. + PredictionOrderOperationResponse = services.PredictionOrderOperationResponse + + // SportsContestCluster groups raw prediction events into a sports contest view. + SportsContestCluster = services.SportsContestCluster + + // QuoteReconciler manages declarative target order diffing and execution. + QuoteReconciler = services.QuoteReconciler + + // CancelAllOrdersOptions protects the REST account-wide cancellation method + // from accidental invocation. + CancelAllOrdersOptions = services.CancelAllOrdersOptions + + // OrderOption configures an outgoing order request. + OrderOption = services.OrderOption + + // BBO captures the current Best Bid and Offer top-of-book snapshot. + BBO = orderbook.BBO + + // OrderEvent represents a private order lifecycle update over WebSockets. + OrderEvent = websocket.OrderEvent + + // OrderPlaceParams contains the typed WebSocket order.place payload. + OrderPlaceParams = websocket.OrderPlaceParams + + // OrderCancelParams contains the typed WebSocket order.cancel payload. + OrderCancelParams = websocket.OrderCancelParams + + // CancelAllOptions protects account-wide WebSocket cancellation methods from accidental invocation. + CancelAllOptions = websocket.CancelAllOptions + + // OrderSide identifies whether a WebSocket order buys or sells. + OrderSide = websocket.OrderSide + + // OrderType identifies the WebSocket order execution style. + OrderType = websocket.OrderType + + // TimeInForce controls how long a WebSocket order remains eligible for execution. + TimeInForce = websocket.TimeInForce + + // EventOutcome identifies the prediction-market outcome attached to a WebSocket order. + EventOutcome = websocket.EventOutcome + + // BalanceUpdate represents an authenticated account balance update. + BalanceUpdate = websocket.BalanceUpdate + + // PositionReport represents an authenticated account position report. + PositionReport = websocket.PositionReport + + // SettlementUpdate represents an authenticated contract settlement update. + SettlementUpdate = websocket.SettlementUpdate + + // ContractStatusEvent represents a public prediction contract lifecycle event. + ContractStatusEvent = websocket.ContractStatusEvent + + // RFQPublicEvent represents an anonymous public combo RFQ discovery event. + RFQPublicEvent = websocket.RFQPublicEvent + + // RFQPrivateDelivery represents an authenticated combo RFQ lifecycle delivery. + RFQPrivateDelivery = websocket.RFQPrivateDelivery + + // RFQSubmitQuoteParams contains the quote submitted by a maker. + RFQSubmitQuoteParams = websocket.RFQSubmitQuoteParams + + // RFQWithdrawQuoteParams identifies a maker quote to withdraw. + RFQWithdrawQuoteParams = websocket.RFQWithdrawQuoteParams + + // RFQConfirmQuoteParams contains the winning maker's last-look decision. + RFQConfirmQuoteParams = websocket.RFQConfirmQuoteParams + + // DepthUpdate represents an incremental L2 order book diff. + DepthUpdate = websocket.DepthUpdate + + // TradeEvent represents a public trade execution. + TradeEvent = websocket.TradeEvent + + // BookTicker represents a top-of-book price and quantity update. + BookTicker = websocket.BookTicker + + // SimulatedFill contains the execution summary of a simulated market order through L2 book depth. + SimulatedFill = orderbook.SimulatedFill +) + +// PageFetcher is a function that fetches a page of items for Go 1.23+ pagination. +type PageFetcher[T any] func(ctx context.Context, offset, limit int) (items []T, hasMore bool, err error) + +// NewPaginator creates a native Go 1.23+ iter.Seq2 iterator for paginated endpoints. +func NewPaginator[T any](ctx context.Context, initialOffset, pageSize int, fetcher PageFetcher[T]) iter.Seq2[T, error] { + return transport.NewPaginator(ctx, initialOffset, pageSize, transport.PageFetcher[T](fetcher)) +} + +// Re-exported helper functions and options. +var ( + // ErrCancelConfirmationRequired indicates that a destructive cancel-all operation was not confirmed. + ErrCancelConfirmationRequired = websocket.ErrCancelConfirmationRequired + + // ErrNoDialerConfigured indicates that no WebSocket transport adapter was configured. + ErrNoDialerConfigured = websocket.ErrNoDialerConfigured + + // ParseDecimal parses a financial number string into a fixed-scale Decimal. + ParseDecimal = types.ParseDecimal + + // MustDecimal parses a decimal string or panics. + MustDecimal = types.MustParseDecimal + + // ParseDecimalNumber parses a decimal string for a generated JSON-number field. + ParseDecimalNumber = types.ParseDecimalNumber + + // MustDecimalNumber parses a decimal string for a generated JSON-number field or panics. + MustDecimalNumber = types.MustParseDecimalNumber + + // ZeroDecimal returns a zero-valued Decimal (0). + ZeroDecimal = types.Zero + + // MinDecimal returns the smaller of two Decimals. + MinDecimal = types.Min + + // MaxDecimal returns the larger of two Decimals. + MaxDecimal = types.Max + + // CalculateNotional computes the total notional value of an order (Price * Quantity). + CalculateNotional = types.CalculateNotional + + // CalculateFee computes the transaction fee in quote currency: Notional * (feeBps / 10000). + CalculateFee = types.CalculateFee + + // CalculatePnL computes the profit/loss and ROI percentage for a position or trade. + CalculatePnL = types.CalculatePnL + + // CalculateLiquidationPrice estimates the bankruptcy liquidation trigger price for a leveraged position. + CalculateLiquidationPrice = types.CalculateLiquidationPrice + + // PredictionMarketPayout calculates financial returns for binary prediction contracts ($1.00 settlement). + PredictionMarketPayout = types.PredictionMarketPayout + + // VerifySignature verifies an incoming Gemini HMAC-SHA384 signature in constant time against a Base64 payload. + VerifySignature = auth.VerifySignature + + // WithClientOrderID attaches a client-specified order ID to fluent order requests. + WithClientOrderID = services.WithClientOrderID + + // WithStopPrice attaches a stop trigger price to fluent order requests. + WithStopPrice = services.WithStopPrice + + // NormalizeContestRoot normalizes a sports event or instrument into its contest root. + NormalizeContestRoot = services.NormalizeContestRoot + + // ExtractCleanContestTitle removes market-family suffixes from sports titles. + ExtractCleanContestTitle = services.ExtractCleanContestTitle + + // BuildSportsContestCluster groups raw sports events into a contest view. + BuildSportsContestCluster = services.BuildSportsContestCluster + + // ClusterSportsEvents groups sports events by contest root. + ClusterSportsEvents = services.ClusterSportsEvents + + // ResolveSportsContest resolves a contest from already-fetched events. + ResolveSportsContest = services.ResolveSportsContest + + // WithToleranceBps configures the acceptable price drift tolerance in basis points. + WithToleranceBps = services.WithToleranceBps + + // WithQuantization configures tick and lot size rounding rules. + WithQuantization = services.WithQuantization + + // WithMaxConcurrentRequests limits concurrent quote cancel and placement requests. + WithMaxConcurrentRequests = services.WithMaxConcurrentRequests +) diff --git a/packages/sdk-go/auth/auth.go b/packages/sdk-go/auth/auth.go new file mode 100644 index 0000000..b15a2d1 --- /dev/null +++ b/packages/sdk-go/auth/auth.go @@ -0,0 +1,82 @@ +package auth + +import ( + "context" + "errors" + "net/http" + "strings" + "unicode" +) + +// ErrInvalidTokenSource indicates that OAuth bearer authentication was +// configured without a usable token source. +var ErrInvalidTokenSource = errors.New("gemini auth: invalid OAuth token source") + +// ErrTokenSourceFailure identifies a runtime failure while obtaining a token +// from a configured OAuth token source. It is distinct from +// ErrInvalidTokenSource, which describes startup configuration. +var ErrTokenSourceFailure = errors.New("gemini auth: OAuth token source failed") + +// ErrInvalidHMACCredentials indicates that HMAC authentication was configured +// without both an API key and API secret. +var ErrInvalidHMACCredentials = errors.New("gemini auth: invalid HMAC credentials") + +// ErrInvalidNonceMode indicates that an HMAC strategy was configured with an +// unsupported nonce mode. +var ErrInvalidNonceMode = errors.New("gemini auth: invalid nonce mode") + +// ErrTimeBasedNonceRequired indicates that a non-time-based API key cannot be +// used for private WebSocket authentication. +var ErrTimeBasedNonceRequired = errors.New("gemini auth: time-based nonce mode is required for WebSocket authentication") + +const ( + authorizationHeader = "Authorization" + geminiAPIKeyHeader = "X-GEMINI-APIKEY" // #nosec G101 -- protocol header name, not a credential value + geminiNonceHeader = "X-GEMINI-NONCE" + geminiPayloadHeader = "X-GEMINI-PAYLOAD" + geminiSignatureHeader = "X-GEMINI-SIGNATURE" +) + +// clearAuthenticationHeaders removes every credential-bearing header owned by +// the SDK. Requests may be reused by callers or across authentication +// strategies, so authentication must never leave a previous scheme attached. +func clearAuthenticationHeaders(header http.Header) { + for _, key := range []string{ + authorizationHeader, + geminiAPIKeyHeader, + geminiNonceHeader, + geminiPayloadHeader, + geminiSignatureHeader, + } { + header.Del(key) + } +} + +func validHeaderCredential(value string) bool { + if strings.TrimSpace(value) == "" { + return false + } + for _, char := range value { + if unicode.IsSpace(char) || unicode.IsControl(char) { + return false + } + } + return true +} + +// Strategy defines the interface for signing and authenticating HTTP requests to Gemini. +type Strategy interface { + // Authenticate modifies the HTTP request in-place with required authentication headers. + Authenticate(ctx context.Context, req *http.Request, payloadJSON []byte) error + + // Key returns the identifier/key for logging/telemetry purposes. + Key() string +} + +// RequestSequencer is implemented by authentication strategies whose protocol +// requires authenticated requests to be dispatched in order. The returned +// release function must be called when the complete request attempt sequence +// has finished. +type RequestSequencer interface { + AcquireRequest(ctx context.Context) (release func(), err error) +} diff --git a/packages/sdk-go/auth/bearer.go b/packages/sdk-go/auth/bearer.go new file mode 100644 index 0000000..3796906 --- /dev/null +++ b/packages/sdk-go/auth/bearer.go @@ -0,0 +1,217 @@ +package auth + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "net/http" + "reflect" + "strings" +) + +// TokenSource provides OAuth 2.0 access tokens dynamically (e.g. for automatic token refresh). +// +// Token is called for each authenticated HTTP attempt, including retries, and +// for each WebSocket connection or reconnect. Implementations should return a +// currently valid token, honor context cancellation, and be safe for concurrent +// calls. The low-level auth package does not persist tokens or perform an +// interactive OAuth authorization-code exchange; the optional oauth package +// provides those protocol helpers. +type TokenSource interface { + // Token returns an active, non-expired access token or an error if renewal fails. + Token(ctx context.Context) (string, error) +} + +// TokenFunc allows using a plain function as a TokenSource. +type TokenFunc func(ctx context.Context) (string, error) + +func (f TokenFunc) Token(ctx context.Context) (string, error) { + return f(ctx) +} + +var _ TokenSource = (TokenFunc)(nil) + +type staticTokenSource struct { + token BearerToken +} + +var _ TokenSource = (*staticTokenSource)(nil) + +func (s staticTokenSource) Token(ctx context.Context) (string, error) { + return string(s.token), nil +} + +// Bearer implements OAuth 2.0 Bearer Token authentication with static or dynamic token sources. +type Bearer struct { + tokenSource TokenSource +} + +var _ Strategy = (*Bearer)(nil) + +// NewBearer creates a new Bearer token authentication strategy using a static token. +func NewBearer(token BearerToken) *Bearer { + return &Bearer{ + tokenSource: staticTokenSource{token: token}, + } +} + +// NewBearerWithSource creates a new Bearer token authentication strategy using a dynamic TokenSource. +func NewBearerWithSource(source TokenSource) *Bearer { + return &Bearer{ + tokenSource: source, + } +} + +// Key returns the identifier for logging. +func (b *Bearer) Key() string { + return "[BEARER_AUTH]" +} + +// Validate reports configuration errors without calling a dynamic token +// source. It is consumed by the high-level client when available, while the +// authentication methods retain their own runtime checks for direct users. +func (b *Bearer) Validate() error { + if b == nil || isNilTokenSource(b.tokenSource) { + return ErrInvalidTokenSource + } + if source, ok := b.tokenSource.(staticTokenSource); ok && !validBearerToken(string(source.token)) { + return fmt.Errorf("%w: static token is empty or contains invalid characters", ErrInvalidTokenSource) + } + return nil +} + +func isNilTokenSource(source TokenSource) bool { + if source == nil { + return true + } + value := reflect.ValueOf(source) + switch value.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice: + return value.IsNil() + default: + return false + } +} + +// Authenticate attaches the Authorization Bearer header and encodes the +// request payload in Gemini's X-GEMINI-PAYLOAD header. OAuth REST requests +// carry no request body; the payload header contains the request path and +// endpoint parameters without a nonce. +func (b *Bearer) Authenticate(ctx context.Context, req *http.Request, payloadJSON []byte) error { + if ctx == nil { + ctx = context.Background() + } + if req == nil { + return fmt.Errorf("gemini auth: nil request") + } + if err := b.Validate(); err != nil { + return err + } + if req.URL == nil { + return fmt.Errorf("gemini auth: request URL is nil") + } + if req.Header == nil { + req.Header = make(http.Header) + } + clearAuthenticationHeaders(req.Header) + rawToken, err := b.token(ctx) + if err != nil { + return err + } + + req.Header.Set(authorizationHeader, fmt.Sprintf("Bearer %s", rawToken)) + + if len(payloadJSON) == 0 { + // Private OAuth endpoints still require X-GEMINI-PAYLOAD even when + // there are no endpoint parameters. Encode an empty JSON object so + // the payload always contains the request path. + payloadJSON = []byte(`{}`) + } + payload, err := buildOAuthPayload(req.URL.Path, payloadJSON) + if err != nil { + return err + } + req.Header.Set(geminiPayloadHeader, base64.StdEncoding.EncodeToString(payload)) + req.Header.Set("Content-Type", "text/plain") + req.Header.Set("Content-Length", "0") + req.Body = http.NoBody + req.ContentLength = 0 + + return nil +} + +// AuthenticateWebSocket attaches the Authorization Bearer header to the WebSocket handshake request. +func (b *Bearer) AuthenticateWebSocket(ctx context.Context, req *http.Request) error { + if ctx == nil { + ctx = context.Background() + } + if req == nil { + return fmt.Errorf("gemini auth: nil request") + } + if err := b.Validate(); err != nil { + return err + } + if req.Header == nil { + req.Header = make(http.Header) + } + clearAuthenticationHeaders(req.Header) + rawToken, err := b.token(ctx) + if err != nil { + return err + } + req.Header.Set(authorizationHeader, fmt.Sprintf("Bearer %s", rawToken)) + return nil +} + +func (b *Bearer) token(ctx context.Context) (string, error) { + if err := b.Validate(); err != nil { + return "", err + } + rawToken, err := b.tokenSource.Token(ctx) + if err != nil { + return "", fmt.Errorf("%w: %w", ErrTokenSourceFailure, err) + } + if strings.TrimSpace(rawToken) == "" { + return "", fmt.Errorf("%w: token source returned an empty token", ErrTokenSourceFailure) + } + if !validBearerToken(rawToken) { + return "", fmt.Errorf("%w: token source returned invalid token characters", ErrTokenSourceFailure) + } + return rawToken, nil +} + +// validBearerToken accepts the RFC 6750 b64token character set. Rejecting +// everything else prevents malformed or header-injection values from reaching +// HTTP or WebSocket transports. +func validBearerToken(value string) bool { + if strings.TrimSpace(value) == "" { + return false + } + for i := 0; i < len(value); i++ { + char := value[i] + if (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || + (char >= '0' && char <= '9') || strings.ContainsRune("-._~+/=", rune(char)) { + continue + } + return false + } + return true +} + +func buildOAuthPayload(requestPath string, payloadJSON []byte) ([]byte, error) { + payloadMap := make(map[string]json.RawMessage) + if err := json.Unmarshal(payloadJSON, &payloadMap); err != nil { + return nil, fmt.Errorf("gemini auth: invalid json payload parameters: %w", err) + } + if payloadMap == nil { + payloadMap = make(map[string]json.RawMessage) + } + requestJSON, err := json.Marshal(requestPath) + if err != nil { + return nil, fmt.Errorf("gemini auth: encoding request path: %w", err) + } + payloadMap["request"] = requestJSON + delete(payloadMap, "nonce") + return json.Marshal(payloadMap) +} diff --git a/packages/sdk-go/auth/bearer_test.go b/packages/sdk-go/auth/bearer_test.go new file mode 100644 index 0000000..8d5d578 --- /dev/null +++ b/packages/sdk-go/auth/bearer_test.go @@ -0,0 +1,375 @@ +package auth_test + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/auth" +) + +type typedNilTokenSource struct{} + +func (*typedNilTokenSource) Token(context.Context) (string, error) { + return "", nil +} + +func TestBearer_StaticToken(t *testing.T) { + token := auth.BearerToken("oauth-access-token-abc-123") + strategy := auth.NewBearer(token) + + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err != nil { + t.Fatalf("failed creating request: %v", err) + } + + if err := strategy.Authenticate(context.Background(), req, nil); err != nil { + t.Fatalf("failed authenticating request: %v", err) + } + + authHeader := req.Header.Get("Authorization") + if authHeader != "Bearer oauth-access-token-abc-123" { + t.Fatalf("expected 'Bearer oauth-access-token-abc-123', got %s", authHeader) + } +} + +func TestBearer_RejectsTypedNilTokenSource(t *testing.T) { + var source *typedNilTokenSource + strategy := auth.NewBearerWithSource(source) + + if err := strategy.Validate(); !errors.Is(err, auth.ErrInvalidTokenSource) { + t.Fatalf("Validate() error = %v, want ErrInvalidTokenSource", err) + } + req, err := http.NewRequest(http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err != nil { + t.Fatalf("failed creating request: %v", err) + } + if err := strategy.Authenticate(context.Background(), req, nil); !errors.Is(err, auth.ErrInvalidTokenSource) { + t.Fatalf("Authenticate() error = %v, want ErrInvalidTokenSource", err) + } +} + +func TestBearer_AuthenticateEncodesPayloadInHeader(t *testing.T) { + strategy := auth.NewBearer(auth.BearerToken("oauth-access-token")) + req, err := http.NewRequest(http.MethodPost, "https://api.gemini.com/v1/mytrades", nil) + if err != nil { + t.Fatalf("failed creating request: %v", err) + } + payload := []byte(`{"request":"ignored","nonce":null,"symbol":"btcusd"}`) + if err := strategy.Authenticate(context.Background(), req, payload); err != nil { + t.Fatalf("failed authenticating request: %v", err) + } + encoded := req.Header.Get("X-GEMINI-PAYLOAD") + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + t.Fatalf("decoding payload header: %v", err) + } + var got map[string]any + if err := json.Unmarshal(decoded, &got); err != nil { + t.Fatalf("decoding payload JSON: %v", err) + } + if got["request"] != "/v1/mytrades" { + t.Fatalf("expected request path in payload, got %v", got["request"]) + } + if got["symbol"] != "btcusd" { + t.Fatalf("expected endpoint parameter in payload, got %v", got["symbol"]) + } + if _, ok := got["nonce"]; ok { + t.Fatal("OAuth payload must not contain a nonce") + } + if req.ContentLength != 0 || req.Body == nil { + t.Fatalf("expected bodyless OAuth request, content length %d", req.ContentLength) + } + body, err := io.ReadAll(req.Body) + if err != nil { + t.Fatalf("reading request body: %v", err) + } + if len(body) != 0 { + t.Fatalf("expected empty request body, got %q", body) + } +} + +func TestBearer_AuthenticateEncodesPayloadForEmptyRequest(t *testing.T) { + strategy := auth.NewBearer(auth.BearerToken("oauth-access-token")) + req, err := http.NewRequest(http.MethodGet, "https://api.gemini.com/v1/prediction-markets/terms/status", nil) + if err != nil { + t.Fatalf("failed creating request: %v", err) + } + if err := strategy.Authenticate(context.Background(), req, nil); err != nil { + t.Fatalf("failed authenticating request: %v", err) + } + + encoded := req.Header.Get("X-GEMINI-PAYLOAD") + if encoded == "" { + t.Fatal("expected X-GEMINI-PAYLOAD for an empty OAuth request") + } + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + t.Fatalf("decoding payload header: %v", err) + } + var got map[string]any + if err := json.Unmarshal(decoded, &got); err != nil { + t.Fatalf("decoding payload JSON: %v", err) + } + if got["request"] != "/v1/prediction-markets/terms/status" { + t.Fatalf("expected request path in payload, got %v", got["request"]) + } +} + +func TestBearer_DynamicTokenSource(t *testing.T) { + currentVal := "initial-token" + source := auth.TokenFunc(func(ctx context.Context) (string, error) { + return currentVal, nil + }) + + strategy := auth.NewBearerWithSource(source) + ctx := context.Background() + + req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err := strategy.Authenticate(ctx, req, nil); err != nil { + t.Fatalf("expected nil auth error, got: %v", err) + } + if req.Header.Get("Authorization") != "Bearer initial-token" { + t.Fatalf("expected initial-token, got %s", req.Header.Get("Authorization")) + } + + // Token refresh simulation + currentVal = "refreshed-token-xyz" + req2, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err := strategy.Authenticate(ctx, req2, nil); err != nil { + t.Fatalf("expected nil auth error, got: %v", err) + } + if req2.Header.Get("Authorization") != "Bearer refreshed-token-xyz" { + t.Fatalf("expected refreshed-token-xyz, got %s", req2.Header.Get("Authorization")) + } + + // Token source failure simulation + errSource := auth.TokenFunc(func(ctx context.Context) (string, error) { + return "", fmt.Errorf("token provider unavailable") + }) + failingStrategy := auth.NewBearerWithSource(errSource) + req3, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err := failingStrategy.Authenticate(ctx, req3, nil); err == nil { + t.Fatal("expected error from failing TokenSource, got nil") + } else if !errors.Is(err, auth.ErrTokenSourceFailure) { + t.Fatalf("expected ErrTokenSourceFailure, got %v", err) + } +} + +func TestBearer_RejectsHeaderUnsafeTokenValues(t *testing.T) { + for _, token := range []auth.BearerToken{"token with spaces", "token\r\nInjected: value", "token\u2028line"} { + strategy := auth.NewBearer(token) + if err := strategy.Validate(); err == nil { + t.Fatalf("Validate() accepted header-unsafe token %q", token) + } + } +} + +func TestBearer_TokenSourceHonorsCancellation(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + strategy := auth.NewBearerWithSource(auth.TokenFunc(func(ctx context.Context) (string, error) { + <-ctx.Done() + return "", ctx.Err() + })) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err != nil { + t.Fatalf("failed creating request: %v", err) + } + + err = strategy.Authenticate(ctx, req, nil) + if !errors.Is(err, context.Canceled) { + t.Fatalf("Authenticate() error = %v, want context.Canceled", err) + } +} + +func TestBearer_TokenSourceSupportsConcurrentCalls(t *testing.T) { + const callers = 8 + entered := make(chan struct{}, callers) + release := make(chan struct{}) + var calls atomic.Int32 + var active atomic.Int32 + var maxActive atomic.Int32 + + source := auth.TokenFunc(func(ctx context.Context) (string, error) { + calls.Add(1) + current := active.Add(1) + for { + previous := maxActive.Load() + if current <= previous || maxActive.CompareAndSwap(previous, current) { + break + } + } + defer active.Add(-1) + entered <- struct{}{} + select { + case <-release: + return "concurrent-token", nil + case <-ctx.Done(): + return "", ctx.Err() + } + }) + strategy := auth.NewBearerWithSource(source) + + var wg sync.WaitGroup + errs := make(chan error, callers) + wg.Add(callers) + for i := 0; i < callers; i++ { + go func() { + defer wg.Done() + req, err := http.NewRequest(http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err != nil { + errs <- err + return + } + errs <- strategy.Authenticate(context.Background(), req, nil) + }() + } + + deadline := time.After(time.Second) + for i := 0; i < callers; i++ { + select { + case <-entered: + case <-deadline: + close(release) + wg.Wait() + t.Fatalf("only %d token-source calls entered concurrently", i) + } + } + close(release) + wg.Wait() + close(errs) + for err := range errs { + if err != nil { + t.Fatalf("concurrent Authenticate() failed: %v", err) + } + } + if got := calls.Load(); got != callers { + t.Fatalf("token source calls = %d, want %d", got, callers) + } + if got := maxActive.Load(); got < 2 { + t.Fatalf("token source max concurrency = %d, want concurrent calls", got) + } +} + +func TestBearer_Validate(t *testing.T) { + tests := []struct { + name string + strategy *auth.Bearer + wantErr bool + }{ + {name: "nil source", strategy: auth.NewBearerWithSource(nil), wantErr: true}, + {name: "nil token func", strategy: auth.NewBearerWithSource(auth.TokenFunc(nil)), wantErr: true}, + {name: "empty static token", strategy: auth.NewBearer(""), wantErr: true}, + {name: "dynamic source", strategy: auth.NewBearerWithSource(auth.TokenFunc(func(context.Context) (string, error) { + return "token", nil + })), wantErr: false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.strategy.Validate() + if (err != nil) != tt.wantErr { + t.Fatalf("Validate() error = %v, wantErr %v", err, tt.wantErr) + } + if tt.wantErr && !errors.Is(err, auth.ErrInvalidTokenSource) { + t.Fatalf("Validate() error = %v, want ErrInvalidTokenSource", err) + } + }) + } +} + +func TestBearerToken_Redaction(t *testing.T) { + token := auth.BearerToken("secret-oauth-bearer-token") + if token.String() != "[REDACTED_TOKEN]" { + t.Fatalf("expected [REDACTED_TOKEN], got %s", token.String()) + } + if token.LogValue().String() != "[REDACTED_TOKEN]" { + t.Fatalf("expected [REDACTED_TOKEN], got %s", token.LogValue().String()) + } + if goStr := token.GoString(); goStr != `auth.BearerToken("[REDACTED_TOKEN]")` { + t.Fatalf("expected GoString redaction, got %s", goStr) + } + + data, err := token.MarshalJSON() + if err != nil || string(data) != `"[REDACTED_TOKEN]"` { + t.Fatalf("expected JSON redaction, got %s (err: %v)", string(data), err) + } +} + +func TestAPIKey_ShortAndMediumLengthKeysAreFullyRedacted(t *testing.T) { + // A prefix+suffix reveal is only safe when it's a minority of the key. + // At 10 characters, revealing 4+4 would expose 80% of the key. + for _, key := range []auth.APIKey{"abcdefghij", "exactly-twenty-chars"} { + if got := key.String(); got != "[REDACTED_KEY]" { + t.Errorf("APIKey(%q).String() = %q, want fully redacted", string(key), got) + } + } +} + +func TestCredentials_FullRedactionCoverage(t *testing.T) { + key := auth.APIKey("my-long-test-api-key-12345") + secret := auth.APISecret("super-secret-hmac-key") + + if key.String() != "my-l...2345" { + t.Fatalf("expected masked key, got %s", key.String()) + } + if key.GoString() != `auth.APIKey("my-l...2345")` { + t.Fatalf("expected GoString masked key, got %s", key.GoString()) + } + + keyJSON, _ := key.MarshalJSON() + if string(keyJSON) != `"my-l...2345"` { + t.Fatalf("expected JSON masked key, got %s", string(keyJSON)) + } + + if secret.String() != "[REDACTED_SECRET]" { + t.Fatalf("expected [REDACTED_SECRET], got %s", secret.String()) + } + if secret.GoString() != `auth.APISecret("[REDACTED_SECRET]")` { + t.Fatalf("expected GoString [REDACTED_SECRET], got %s", secret.GoString()) + } + + secretJSON, _ := secret.MarshalJSON() + if string(secretJSON) != `"[REDACTED_SECRET]"` { + t.Fatalf("expected JSON [REDACTED_SECRET], got %s", string(secretJSON)) + } +} + +func TestBearer_ErrorPropagation(t *testing.T) { + ctx := context.Background() + req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.gemini.com/v1/balances", nil) + if err != nil { + t.Fatalf("failed creating request: %v", err) + } + + // 1. NewBearerWithSource(nil) must return error on Authenticate + nilStrategy := auth.NewBearerWithSource(nil) + if err := nilStrategy.Authenticate(ctx, req, nil); err == nil { + t.Fatal("expected error with nil TokenSource, got nil") + } + + // 2. TokenSource error must propagate wrapped + sourceErr := fmt.Errorf("oauth token renewal failure") + failingSource := auth.TokenFunc(func(ctx context.Context) (string, error) { + return "", sourceErr + }) + + failingStrategy := auth.NewBearerWithSource(failingSource) + if err := failingStrategy.Authenticate(ctx, req, nil); err == nil { + t.Fatal("expected error from failing TokenSource, got nil") + } + + if key := failingStrategy.Key(); key != "[BEARER_AUTH]" { + t.Fatalf("expected key [BEARER_AUTH], got %s", key) + } +} diff --git a/packages/sdk-go/auth/fuzz_test.go b/packages/sdk-go/auth/fuzz_test.go new file mode 100644 index 0000000..8caea24 --- /dev/null +++ b/packages/sdk-go/auth/fuzz_test.go @@ -0,0 +1,44 @@ +package auth_test + +import ( + "encoding/base64" + "encoding/json" + "testing" + "unicode/utf8" + + "github.com/gemini/developer-platform/packages/sdk-go/auth" +) + +func FuzzHMAC_BuildPayload(f *testing.F) { + f.Add("/v1/order/new", []byte(`{"symbol":"btcusd","amount":"1.0","price":"65000.00","side":"buy"}`)) + f.Add("/v1/order/cancel", []byte(`{"order_id":"123456"}`)) + f.Add("/v1/balances", []byte(`{}`)) + f.Add("/v1/heartbeat", []byte(``)) + + signer := auth.NewHMAC(auth.APIKey("my-key"), auth.APISecret("my-secret")) + + f.Fuzz(func(t *testing.T, path string, customParams []byte) { + if !utf8.ValidString(path) { + return + } + payload, err := signer.BuildPayload(path, customParams) + if err != nil { + return + } + var envelope map[string]json.RawMessage + if err := json.Unmarshal(payload, &envelope); err != nil { + t.Fatalf("BuildPayload returned invalid JSON: %v", err) + } + var gotPath, gotNonce string + if err := json.Unmarshal(envelope["request"], &gotPath); err != nil || gotPath != path { + t.Fatalf("BuildPayload did not preserve request path %q", path) + } + if err := json.Unmarshal(envelope["nonce"], &gotNonce); err != nil || gotNonce == "" { + t.Fatal("BuildPayload did not inject a valid nonce") + } + b64Payload := base64.StdEncoding.EncodeToString(payload) + if !auth.VerifySignature(auth.APISecret("my-secret"), b64Payload, signer.Sign([]byte(b64Payload))) { + t.Fatal("generated signature did not verify against generated payload") + } + }) +} diff --git a/packages/sdk-go/auth/hmac.go b/packages/sdk-go/auth/hmac.go new file mode 100644 index 0000000..2f45eef --- /dev/null +++ b/packages/sdk-go/auth/hmac.go @@ -0,0 +1,412 @@ +package auth + +import ( + "bytes" + "context" + "crypto/hmac" + "crypto/sha512" + "encoding/base64" + "encoding/hex" + "encoding/json" + "fmt" + "hash" + "io" + "net/http" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" +) + +// NonceGenerator generates nonce strings. +type NonceGenerator interface { + Next() string +} + +type monotonicNonce struct { + lastNonce atomic.Int64 + skewOffset atomic.Int64 // Skew in nanoseconds + nowFunc func() time.Time + unit func(time.Time) int64 +} + +var _ NonceGenerator = (*monotonicNonce)(nil) + +func newMonotonicNonce(nowFunc func() time.Time) *monotonicNonce { + if nowFunc == nil { + nowFunc = time.Now + } + return &monotonicNonce{ + nowFunc: nowFunc, + unit: func(now time.Time) int64 { return now.UnixMilli() }, + } +} + +func newSecondNonce(nowFunc func() time.Time) *monotonicNonce { + if nowFunc == nil { + nowFunc = time.Now + } + return &monotonicNonce{ + nowFunc: nowFunc, + unit: func(now time.Time) int64 { return now.Unix() }, + } +} + +type timeBasedNonce struct { + skewOffset atomic.Int64 // Skew in nanoseconds + nowFunc func() time.Time +} + +func newTimeBasedNonce(nowFunc func() time.Time) *timeBasedNonce { + if nowFunc == nil { + nowFunc = time.Now + } + return &timeBasedNonce{nowFunc: nowFunc} +} + +func (n *timeBasedNonce) SetSkew(skew time.Duration) { + n.skewOffset.Store(int64(skew)) +} + +func (n *timeBasedNonce) Next() string { + skew := time.Duration(n.skewOffset.Load()) + return strconv.FormatInt(n.nowFunc().Add(skew).Unix(), 10) +} + +func (m *monotonicNonce) SetSkew(skew time.Duration) { + m.skewOffset.Store(int64(skew)) +} + +func (m *monotonicNonce) Next() string { + skew := time.Duration(m.skewOffset.Load()) + now := m.unit(m.nowFunc().Add(skew)) + for { + last := m.lastNonce.Load() + next := now + if next <= last { + next = last + 1 + } + if m.lastNonce.CompareAndSwap(last, next) { + return strconv.FormatInt(next, 10) + } + } +} + +// ClockSkewCalibrator allows calibrating local timestamp generation against remote server time. +type ClockSkewCalibrator interface { + CalibrateServerTime(serverTime time.Time) +} + +// NonceMode identifies the API-key nonce contract used by an HMAC strategy. +// Monotonic mode is appropriate for REST API keys that require strictly +// increasing millisecond nonces. Time-based mode uses epoch seconds for both +// REST and private WebSocket authentication, as required by time-based keys. +type NonceMode uint8 + +const ( + NonceModeMonotonic NonceMode = iota + NonceModeTimeBased +) + +func (m NonceMode) valid() bool { + return m == NonceModeMonotonic || m == NonceModeTimeBased +} + +// HMAC implements Gemini's HMAC-SHA384 payload signing authentication strategy. +type HMAC struct { + key APIKey + secret APISecret + nonceMode NonceMode + nonces NonceGenerator + wsNonces NonceGenerator + requestGate chan struct{} + hasherPool sync.Pool + configurationErr error +} + +var ( + _ Strategy = (*HMAC)(nil) + _ ClockSkewCalibrator = (*HMAC)(nil) + _ RequestSequencer = (*HMAC)(nil) +) + +type HMACOption func(*HMAC) + +// WithNonceMode selects the nonce contract for the HMAC strategy. The option +// updates both REST and WebSocket defaults so a time-based strategy can safely +// authenticate both surfaces with the same API key. +func WithNonceMode(mode NonceMode) HMACOption { + return func(h *HMAC) { + if !mode.valid() { + h.configurationErr = fmt.Errorf("%w: %d", ErrInvalidNonceMode, mode) + return + } + h.nonceMode = mode + if mode == NonceModeTimeBased { + h.nonces = newTimeBasedNonce(time.Now) + h.wsNonces = newTimeBasedNonce(time.Now) + return + } + h.nonces = newMonotonicNonce(time.Now) + h.wsNonces = newSecondNonce(time.Now) + } +} + +// WithCustomNonceGenerator allows injecting a deterministic or custom nonce generator. +func WithCustomNonceGenerator(gen NonceGenerator) HMACOption { + return func(h *HMAC) { + if gen != nil { + h.nonces = gen + } + } +} + +// NewHMAC creates a new HMAC-SHA384 authentication strategy with monotonic nonce generator. +func NewHMAC(key APIKey, secret APISecret, opts ...HMACOption) *HMAC { + h := &HMAC{ + key: key, + secret: secret, + nonceMode: NonceModeMonotonic, + nonces: newMonotonicNonce(time.Now), + wsNonces: newSecondNonce(time.Now), + requestGate: make(chan struct{}, 1), + } + h.requestGate <- struct{}{} + h.hasherPool.New = func() any { + return hmac.New(sha512.New384, []byte(secret)) + } + for _, opt := range opts { + opt(h) + } + return h +} + +// NewTimeBasedHMAC creates an HMAC strategy for a time-based API key. Its +// epoch-second nonce generator is valid for both private REST and WebSocket +// authentication. +func NewTimeBasedHMAC(key APIKey, secret APISecret, opts ...HMACOption) *HMAC { + allOpts := make([]HMACOption, 0, len(opts)+1) + allOpts = append(allOpts, WithNonceMode(NonceModeTimeBased)) + allOpts = append(allOpts, opts...) + return NewHMAC(key, secret, allOpts...) +} + +// Validate reports whether the HMAC strategy has usable credentials. +func (h *HMAC) Validate() error { + if h == nil || !validHeaderCredential(string(h.key)) || strings.TrimSpace(string(h.secret)) == "" { + return ErrInvalidHMACCredentials + } + if h.configurationErr != nil { + return h.configurationErr + } + if !h.nonceMode.valid() { + return fmt.Errorf("%w: %d", ErrInvalidNonceMode, h.nonceMode) + } + return nil +} + +// Key returns a masked API-key identifier suitable for logs and telemetry. +func (h *HMAC) Key() string { + return h.key.String() +} + +// AcquireRequest serializes a complete authenticated request attempt sequence. +// Gemini rejects a request when its nonce arrives after a larger nonce from the +// same API key, so the gate must remain held through transport retries. +func (h *HMAC) AcquireRequest(ctx context.Context) (func(), error) { + if err := h.Validate(); err != nil { + return nil, err + } + if ctx == nil { + ctx = context.Background() + } + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-h.requestGate: + return func() { h.requestGate <- struct{}{} }, nil + } +} + +// NextNonce returns the next nonce for the configured nonce mode. +func (h *HMAC) NextNonce() string { + return h.nonces.Next() +} + +// CalibrateServerTime adjusts nonce timestamps based on remote Gemini server time. +func (h *HMAC) CalibrateServerTime(serverTime time.Time) { + skew := time.Until(serverTime) + if mono, ok := h.nonces.(*monotonicNonce); ok { + mono.SetSkew(skew) + } + if mono, ok := h.wsNonces.(*monotonicNonce); ok { + mono.SetSkew(skew) + } + if timestamp, ok := h.nonces.(*timeBasedNonce); ok { + timestamp.SetSkew(skew) + } + if timestamp, ok := h.wsNonces.(*timeBasedNonce); ok { + timestamp.SetSkew(skew) + } +} + +// BuildPayload constructs the Gemini payload map with request path and nonce injected. +func (h *HMAC) BuildPayload(requestPath string, customParams []byte) ([]byte, error) { + if err := h.Validate(); err != nil { + return nil, err + } + trimmed := bytes.TrimSpace(customParams) + nonce := h.NextNonce() + + payloadMap := make(map[string]json.RawMessage) + if len(trimmed) > 0 && !bytes.Equal(trimmed, []byte("null")) { + if err := json.Unmarshal(trimmed, &payloadMap); err != nil { + return nil, fmt.Errorf("gemini auth: invalid json payload parameters: %w", err) + } + if payloadMap == nil { + payloadMap = make(map[string]json.RawMessage) + } + } + + requestJSON, err := json.Marshal(requestPath) + if err != nil { + return nil, fmt.Errorf("gemini auth: encoding request path: %w", err) + } + nonceJSON, err := json.Marshal(nonce) + if err != nil { + return nil, fmt.Errorf("gemini auth: encoding nonce: %w", err) + } + payloadMap["request"] = requestJSON + payloadMap["nonce"] = nonceJSON + + return json.Marshal(payloadMap) +} + +func hashToHex(hasher hash.Hash) string { + var sumBuf [48]byte + sum := hasher.Sum(sumBuf[:0]) + var hexBuf [96]byte + hex.Encode(hexBuf[:], sum) + return string(hexBuf[:]) +} + +// Sign calculates the HMAC-SHA384 hex signature of a base64 encoded payload. +func (h *HMAC) Sign(b64Payload []byte) string { + if h == nil || h.Validate() != nil { + return "" + } + hasher, ok := h.hasherPool.Get().(hash.Hash) + if !ok || hasher == nil { + return "" + } + hasher.Reset() + hasher.Write(b64Payload) + sig := hashToHex(hasher) + h.hasherPool.Put(hasher) + return sig +} + +// SignString calculates the HMAC-SHA384 hex signature of a base64 encoded string payload. +func (h *HMAC) SignString(b64Payload string) string { + if h == nil || h.Validate() != nil { + return "" + } + hasher, ok := h.hasherPool.Get().(hash.Hash) + if !ok || hasher == nil { + return "" + } + hasher.Reset() + _, _ = io.WriteString(hasher, b64Payload) + sig := hashToHex(hasher) + h.hasherPool.Put(hasher) + return sig +} + +// Authenticate prepares the HTTP request according to Gemini private REST protocol. +func (h *HMAC) Authenticate(ctx context.Context, req *http.Request, payloadJSON []byte) error { + if ctx != nil { + if err := ctx.Err(); err != nil { + return err + } + } + if req == nil { + return fmt.Errorf("gemini auth: nil request") + } + if err := h.Validate(); err != nil { + return err + } + if req.Header == nil { + req.Header = make(http.Header) + } + clearAuthenticationHeaders(req.Header) + if req.URL == nil { + return fmt.Errorf("gemini auth: request URL is nil") + } + fullPayload, err := h.BuildPayload(req.URL.Path, payloadJSON) + if err != nil { + return err + } + + b64Payload := base64.StdEncoding.EncodeToString(fullPayload) + signature := h.SignString(b64Payload) + + req.Header.Set("Content-Type", "text/plain") + req.Header.Set("Content-Length", "0") + req.Header.Set(geminiAPIKeyHeader, string(h.key)) + req.Header.Set(geminiPayloadHeader, b64Payload) + req.Header.Set(geminiSignatureHeader, signature) + req.Header.Set("Cache-Control", "no-cache") + + // Ensure empty body on the wire + req.Body = http.NoBody + req.ContentLength = 0 + + return nil +} + +// AuthenticateWebSocket prepares handshake HTTP headers for Gemini private WebSocket feeds. +func (h *HMAC) AuthenticateWebSocket(ctx context.Context, req *http.Request) error { + if ctx != nil { + if err := ctx.Err(); err != nil { + return err + } + } + if req == nil { + return fmt.Errorf("gemini auth: nil request") + } + if err := h.Validate(); err != nil { + return err + } + if h.nonceMode != NonceModeTimeBased { + return ErrTimeBasedNonceRequired + } + if req.Header == nil { + req.Header = make(http.Header) + } + clearAuthenticationHeaders(req.Header) + nonce := h.wsNonces.Next() + b64Payload := base64.StdEncoding.EncodeToString([]byte(nonce)) + signature := h.SignString(b64Payload) + + req.Header.Set(geminiAPIKeyHeader, string(h.key)) + req.Header.Set(geminiNonceHeader, nonce) + req.Header.Set(geminiPayloadHeader, b64Payload) + req.Header.Set(geminiSignatureHeader, signature) + return nil +} + +// VerifySignature verifies an incoming Gemini HMAC-SHA384 signature in constant time against a Base64-encoded payload. +func VerifySignature(secret APISecret, b64Payload, signature string) bool { + if strings.TrimSpace(string(secret)) == "" || len(signature) != hex.EncodedLen(sha512.Size384) { + return false + } + provided, err := hex.DecodeString(signature) + if err != nil { + return false + } + + hasher := hmac.New(sha512.New384, []byte(secret)) + _, _ = io.WriteString(hasher, b64Payload) + return hmac.Equal(hasher.Sum(nil), provided) +} diff --git a/packages/sdk-go/auth/hmac_test.go b/packages/sdk-go/auth/hmac_test.go new file mode 100644 index 0000000..3d4c7b4 --- /dev/null +++ b/packages/sdk-go/auth/hmac_test.go @@ -0,0 +1,429 @@ +package auth + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "sync" + "testing" + "time" +) + +func TestMonotonicNonce_Concurrency(t *testing.T) { + fakeTime := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC) + gen := newMonotonicNonce(func() time.Time { + return fakeTime + }) + + const goroutines = 50 + const iterations = 500 + results := make([][]int64, goroutines) + var wg sync.WaitGroup + + for i := 0; i < goroutines; i++ { + wg.Add(1) + go func(workerID int) { + defer wg.Done() + workerResults := make([]int64, iterations) + for j := 0; j < iterations; j++ { + nStr := gen.Next() + val, err := strconv.ParseInt(nStr, 10, 64) + if err != nil { + t.Errorf("worker %d: invalid int: %v", workerID, err) + return + } + workerResults[j] = val + } + results[workerID] = workerResults + }(i) + } + + wg.Wait() + + seen := make(map[int64]bool, goroutines*iterations) + for workerID, workerResults := range results { + for _, nonce := range workerResults { + if seen[nonce] { + t.Fatalf("duplicate nonce detected from worker %d: %d", workerID, nonce) + } + seen[nonce] = true + } + } + + if len(seen) != goroutines*iterations { + t.Fatalf("expected %d unique nonces, got %d", goroutines*iterations, len(seen)) + } +} + +func TestTimeBasedNonce_RemainsAtCurrentEpochSecond(t *testing.T) { + fixedTime := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC) + gen := newTimeBasedNonce(func() time.Time { return fixedTime }) + want := strconv.FormatInt(fixedTime.Unix(), 10) + + for i := 0; i < 100; i++ { + if got := gen.Next(); got != want { + t.Fatalf("nonce %d = %q, want current epoch second %q", i, got, want) + } + } +} + +func TestHMAC_Authenticate(t *testing.T) { + key := APIKey("my-test-api-key") + secret := APISecret("my-test-secret-12345") + + fixedTime := time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC) + gen := newMonotonicNonce(func() time.Time { return fixedTime }) + + h := NewHMAC(key, secret, WithCustomNonceGenerator(gen)) + + req := httptest.NewRequest("POST", "https://api.gemini.com/v1/order/new", nil) + customParams := []byte(`{"symbol":"btcusd","amount":"1.5","price":"65000.00","side":"buy","type":"exchange limit"}`) + + err := h.Authenticate(context.Background(), req, customParams) + if err != nil { + t.Fatalf("Authenticate failed: %v", err) + } + + if req.Header.Get("X-GEMINI-APIKEY") != "my-test-api-key" { + t.Errorf("expected API key header, got %s", req.Header.Get("X-GEMINI-APIKEY")) + } + + payloadB64 := req.Header.Get("X-GEMINI-PAYLOAD") + if payloadB64 == "" { + t.Fatal("expected X-GEMINI-PAYLOAD header") + } + + decodedBytes, err := base64.StdEncoding.DecodeString(payloadB64) + if err != nil { + t.Fatalf("failed decoding payload base64: %v", err) + } + + var parsed map[string]any + if err := json.Unmarshal(decodedBytes, &parsed); err != nil { + t.Fatalf("failed unmarshaling payload: %v", err) + } + + if parsed["request"] != "/v1/order/new" { + t.Errorf("expected request path /v1/order/new, got %v", parsed["request"]) + } + if parsed["symbol"] != "btcusd" { + t.Errorf("expected symbol btcusd, got %v", parsed["symbol"]) + } + if parsed["nonce"] != strconv.FormatInt(fixedTime.UnixMilli(), 10) { + t.Errorf("expected nonce %d, got %v", fixedTime.UnixMilli(), parsed["nonce"]) + } + + sig := req.Header.Get("X-GEMINI-SIGNATURE") + if sig == "" { + t.Fatal("expected X-GEMINI-SIGNATURE header") + } + if !VerifySignature(secret, payloadB64, sig) { + t.Fatal("expected X-GEMINI-SIGNATURE to cryptographically match payload and secret") + } + if req.ContentLength != 0 { + t.Errorf("expected ContentLength 0, got %d", req.ContentLength) + } + if req.Body != http.NoBody { + t.Errorf("expected req.Body to be http.NoBody") + } +} + +func TestAuthenticationStrategiesClearReservedHeaders(t *testing.T) { + req := httptest.NewRequest("POST", "https://api.gemini.com/v1/order/new", nil) + req.Header = http.Header{ + "Authorization": {"Bearer stale-token"}, + "X-GEMINI-APIKEY": {"stale-key"}, + "X-GEMINI-NONCE": {"stale-nonce"}, + "X-GEMINI-PAYLOAD": {"stale-payload"}, + "X-GEMINI-SIGNATURE": {"stale-signature"}, + } + + hmacStrategy := NewHMAC(APIKey("hmac-key"), APISecret("hmac-secret")) + if err := hmacStrategy.Authenticate(context.Background(), req, []byte(`{"symbol":"btcusd"}`)); err != nil { + t.Fatalf("HMAC Authenticate failed: %v", err) + } + if got := req.Header.Get(authorizationHeader); got != "" { + t.Fatalf("HMAC authentication retained Authorization header %q", got) + } + if got := req.Header.Get(geminiNonceHeader); got != "" { + t.Fatalf("HMAC REST authentication retained nonce header %q", got) + } + + bearerStrategy := NewBearer(BearerToken("bearer-token")) + if err := bearerStrategy.Authenticate(context.Background(), req, []byte(`{"symbol":"btcusd"}`)); err != nil { + t.Fatalf("Bearer Authenticate failed: %v", err) + } + if got := req.Header.Get(authorizationHeader); got != "Bearer bearer-token" { + t.Fatalf("Bearer authentication header = %q", got) + } + for _, key := range []string{geminiAPIKeyHeader, geminiNonceHeader, geminiSignatureHeader} { + if got := req.Header.Get(key); got != "" { + t.Fatalf("Bearer authentication retained %s header %q", key, got) + } + } +} + +func TestHMAC_ValidateRejectsMissingCredentials(t *testing.T) { + for name, strategy := range map[string]*HMAC{ + "nil": nil, + "empty key": NewHMAC("", "secret"), + "key with space": NewHMAC("key with space", "secret"), + "key with newline": NewHMAC("key\nwith-newline", "secret"), + "empty secret": NewHMAC("key", ""), + "zero value": &HMAC{}, + } { + t.Run(name, func(t *testing.T) { + if err := strategy.Validate(); err != ErrInvalidHMACCredentials { + t.Fatalf("Validate() error = %v, want ErrInvalidHMACCredentials", err) + } + }) + } + if err := NewHMAC("key", "secret", WithNonceMode(NonceMode(99))).Validate(); !errors.Is(err, ErrInvalidNonceMode) { + t.Fatalf("invalid nonce mode error = %v, want ErrInvalidNonceMode", err) + } +} + +func TestHMAC_AuthenticateWebSocket(t *testing.T) { + key := APIKey("my-ws-api-key") + secret := APISecret("my-ws-secret-67890") + h := NewTimeBasedHMAC(key, secret) + + req := httptest.NewRequest("GET", "wss://ws.gemini.com/v1/marketdata", nil) + err := h.AuthenticateWebSocket(context.Background(), req) + if err != nil { + t.Fatalf("AuthenticateWebSocket failed: %v", err) + } + + apiKey := req.Header.Get("X-GEMINI-APIKEY") + if apiKey != "my-ws-api-key" { + t.Fatalf("expected X-GEMINI-APIKEY my-ws-api-key, got %s", apiKey) + } + + nonceStr := req.Header.Get("X-GEMINI-NONCE") + if nonceStr == "" { + t.Fatal("expected non-empty X-GEMINI-NONCE header") + } + nonceVal, err := strconv.ParseInt(nonceStr, 10, 64) + if err != nil || nonceVal <= 0 { + t.Fatalf("expected valid monotonic integer for X-GEMINI-NONCE, got %s", nonceStr) + } + if nonceVal < time.Now().Add(-time.Second).Unix() { + t.Fatalf("expected epoch-second nonce near current time, got %d", nonceVal) + } + + payloadB64 := req.Header.Get("X-GEMINI-PAYLOAD") + if payloadB64 == "" { + t.Fatal("expected non-empty X-GEMINI-PAYLOAD header") + } + decodedBytes, err := base64.StdEncoding.DecodeString(payloadB64) + if err != nil { + t.Fatalf("failed decoding X-GEMINI-PAYLOAD base64: %v", err) + } + if string(decodedBytes) != nonceStr { + t.Fatalf("expected decoded X-GEMINI-PAYLOAD %s, got %s", nonceStr, string(decodedBytes)) + } + + sig := req.Header.Get("X-GEMINI-SIGNATURE") + if sig == "" { + t.Fatal("expected non-empty X-GEMINI-SIGNATURE header") + } + if !VerifySignature(secret, payloadB64, sig) { + t.Fatal("expected X-GEMINI-SIGNATURE to cryptographically match X-GEMINI-PAYLOAD and secret") + } +} + +func TestHMAC_MonotonicNonceRejectsWebSocketAuthentication(t *testing.T) { + h := NewHMAC("key", "secret") + req := httptest.NewRequest("GET", "wss://ws.gemini.com/v1/marketdata", nil) + if err := h.AuthenticateWebSocket(context.Background(), req); !errors.Is(err, ErrTimeBasedNonceRequired) { + t.Fatalf("AuthenticateWebSocket() error = %v, want ErrTimeBasedNonceRequired", err) + } +} + +func TestTimeBasedHMACSupportsRESTAndWebSocketAuthentication(t *testing.T) { + fixedTime := time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC) + h := NewTimeBasedHMAC(APIKey("key"), APISecret("secret")) + h.nonces = newTimeBasedNonce(func() time.Time { return fixedTime }) + h.wsNonces = newTimeBasedNonce(func() time.Time { return fixedTime }) + + restReq := httptest.NewRequest("POST", "https://api.gemini.com/v1/order/new", nil) + if err := h.Authenticate(context.Background(), restReq, nil); err != nil { + t.Fatalf("REST Authenticate() failed: %v", err) + } + decoded, err := base64.StdEncoding.DecodeString(restReq.Header.Get(geminiPayloadHeader)) + if err != nil { + t.Fatalf("decoding REST payload: %v", err) + } + var payload map[string]string + if err := json.Unmarshal(decoded, &payload); err != nil { + t.Fatalf("decoding REST payload JSON: %v", err) + } + if payload["nonce"] != strconv.FormatInt(fixedTime.Unix(), 10) { + t.Fatalf("REST nonce = %q, want %d", payload["nonce"], fixedTime.Unix()) + } + + wsReq := httptest.NewRequest("GET", "wss://ws.gemini.com/v1/marketdata", nil) + if err := h.AuthenticateWebSocket(context.Background(), wsReq); err != nil { + t.Fatalf("WebSocket Authenticate() failed: %v", err) + } + if got := wsReq.Header.Get(geminiNonceHeader); got != strconv.FormatInt(fixedTime.Unix(), 10) { + t.Fatalf("WebSocket nonce = %q, want %d", got, fixedTime.Unix()) + } +} + +func TestNewTimeBasedHMAC_AppliesCustomNonceGenerator(t *testing.T) { + gen := newMonotonicNonce(func() time.Time { return time.UnixMilli(123) }) + h := NewTimeBasedHMAC("key", "secret", WithCustomNonceGenerator(gen)) + + if got := h.NextNonce(); got != "123" { + t.Fatalf("NextNonce() = %q, want custom generator nonce 123", got) + } +} + +func TestHMAC_BuildPayloadPreservesJSONAndEscapesRequestPath(t *testing.T) { + h := NewHMAC("key", "secret", WithCustomNonceGenerator(newMonotonicNonce(func() time.Time { + return time.UnixMilli(123) + }))) + + built, err := h.BuildPayload(`/v1/quote/"slash\\value`, []byte(`{"amount":9007199254740993,"request":"spoofed","nonce":0}`)) + if err != nil { + t.Fatalf("BuildPayload failed: %v", err) + } + + var payload map[string]json.RawMessage + if err := json.Unmarshal(built, &payload); err != nil { + t.Fatalf("failed decoding payload: %v", err) + } + var request, nonce string + if err := json.Unmarshal(payload["request"], &request); err != nil { + t.Fatalf("request was not encoded as a string: %v", err) + } + if request != `/v1/quote/"slash\\value` { + t.Fatalf("unexpected request path %q", request) + } + if err := json.Unmarshal(payload["nonce"], &nonce); err != nil { + t.Fatalf("nonce was not encoded as a string: %v", err) + } + if nonce != "123" { + t.Fatalf("expected nonce 123, got %q", nonce) + } + if got := string(payload["amount"]); got != "9007199254740993" { + t.Fatalf("large JSON number was changed: got %s", got) + } +} + +func TestHMAC_KeyDoesNotExposeSecret(t *testing.T) { + h := NewHMAC(APIKey("public-key"), APISecret("super-secret")) + if got := h.Key(); got != APIKey("public-key").String() { + t.Fatalf("expected masked key identifier, got %q", got) + } + if h.Key() == "public-key" { + t.Fatal("HMAC Key exposed the full API key") + } + if strings.Contains(h.Key(), "super-secret") { + t.Fatal("HMAC Key exposed the API secret") + } +} + +func TestVerifySignature(t *testing.T) { + secret := APISecret("super-secret-key-98765") + b64Payload := "eyJyZXF1ZXN0IjoiL3YxL29yZGVyL3N0YXR1cyIsIm5vbmNlIjoiMTIzNDU2Nzg5In0=" + + h := NewHMAC("any-key", secret) + validSig := h.Sign([]byte(b64Payload)) + + if !VerifySignature(secret, b64Payload, validSig) { + t.Fatal("expected valid signature to verify successfully") + } + + // Test case insensitivity of hex string + if !VerifySignature(secret, b64Payload, strings.ToUpper(validSig)) { + t.Fatal("expected uppercase signature verification to succeed") + } + + // Invalid signature + if VerifySignature(secret, b64Payload, "deadbeef1234567890abcdef") { + t.Fatal("expected invalid signature to fail verification") + } + + // Wrong secret + if VerifySignature(APISecret("wrong-secret"), b64Payload, validSig) { + t.Fatal("expected wrong secret to fail verification") + } + + // Tampered payload + if VerifySignature(secret, "tampered-payload", validSig) { + t.Fatal("expected tampered payload to fail verification") + } + + if VerifySignature("", b64Payload, NewHMAC("any-key", "").Sign([]byte(b64Payload))) { + t.Fatal("expected an empty HMAC secret to fail closed") + } + if VerifySignature(secret, b64Payload, strings.Repeat("g", 96)) { + t.Fatal("expected malformed hexadecimal signature to fail verification") + } +} + +func TestHMAC_BuildPayload_NoDuplicateEnvelopeKeys(t *testing.T) { + key := APIKey("test-key") + secret := APISecret("test-secret") + h := NewHMAC(key, secret) + + // Simulate generated OpenAPI struct payload with zero-valued envelope fields + structJSON := []byte(`{"amount":"1.0","nonce":0,"price":"50000","request":"","side":"buy","symbol":"btcusd"}`) + built, err := h.BuildPayload("/v1/order/new", structJSON) + if err != nil { + t.Fatalf("BuildPayload failed: %v", err) + } + + // Verify only one occurrence of "request" and "nonce" in wire JSON + s := string(built) + if strings.Count(s, `"request"`) != 1 { + t.Fatalf("expected exactly 1 'request' key in payload, got %d in: %s", strings.Count(s, `"request"`), s) + } + if strings.Count(s, `"nonce"`) != 1 { + t.Fatalf("expected exactly 1 'nonce' key in payload, got %d in: %s", strings.Count(s, `"nonce"`), s) + } + + var parsed map[string]any + if err := json.Unmarshal(built, &parsed); err != nil { + t.Fatalf("failed unmarshaling built payload: %v", err) + } + if parsed["request"] != "/v1/order/new" { + t.Fatalf("expected request /v1/order/new, got %v", parsed["request"]) + } + if parsed["amount"] != "1.0" { + t.Fatalf("expected amount 1.0, got %v", parsed["amount"]) + } +} + +func BenchmarkHMAC_Authenticate(b *testing.B) { + key := APIKey("my-test-api-key") + secret := APISecret("my-test-secret-12345") + h := NewHMAC(key, secret) + req := httptest.NewRequest("POST", "https://api.gemini.com/v1/order/new", nil) + customParams := []byte(`{"symbol":"btcusd","amount":"1.5","price":"65000.00","side":"buy","type":"exchange limit"}`) + ctx := context.Background() + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + _ = h.Authenticate(ctx, req, customParams) + } +} + +func BenchmarkMonotonicNonce_Next(b *testing.B) { + gen := newMonotonicNonce(time.Now) + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + _ = gen.Next() + } +} diff --git a/packages/sdk-go/auth/secrets.go b/packages/sdk-go/auth/secrets.go new file mode 100644 index 0000000..526a357 --- /dev/null +++ b/packages/sdk-go/auth/secrets.go @@ -0,0 +1,82 @@ +package auth + +import ( + "fmt" + "log/slog" +) + +// APIKey represents a Gemini API Key identifier. +type APIKey string + +// String masks the API key for safe terminal/log output. It only reveals an +// 8-character prefix+suffix fingerprint when the key is long enough that the +// reveal is a minority of the key (at most ~40%); shorter keys are fully +// redacted so a short-to-medium key can't have most of itself exposed. +func (k APIKey) String() string { + raw := string(k) + if len(raw) <= 20 { + return "[REDACTED_KEY]" + } + return fmt.Sprintf("%s...%s", raw[:4], raw[len(raw)-4:]) +} + +// GoString masks the API key in %#v debug representations. +func (k APIKey) GoString() string { + return fmt.Sprintf("auth.APIKey(%q)", k.String()) +} + +// MarshalJSON redacts the API key during JSON serialization. +func (k APIKey) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf("%q", k.String())), nil +} + +// LogValue implements slog.LogValuer to prevent accidental leaking in structured logs. +func (k APIKey) LogValue() slog.Value { + return slog.StringValue(k.String()) +} + +// APISecret represents a Gemini API secret used for HMAC-SHA384 signatures. +type APISecret string + +// String completely redacts the API secret. +func (s APISecret) String() string { + return "[REDACTED_SECRET]" +} + +// GoString completely redacts the API secret in %#v debug representations. +func (s APISecret) GoString() string { + return `auth.APISecret("[REDACTED_SECRET]")` +} + +// MarshalJSON redacts the API secret during JSON serialization. +func (s APISecret) MarshalJSON() ([]byte, error) { + return []byte(`"[REDACTED_SECRET]"`), nil +} + +// LogValue implements slog.LogValuer. +func (s APISecret) LogValue() slog.Value { + return slog.StringValue("[REDACTED_SECRET]") +} + +// BearerToken represents an OAuth2 bearer access token. +type BearerToken string + +// String completely redacts the bearer token. +func (t BearerToken) String() string { + return "[REDACTED_TOKEN]" +} + +// GoString completely redacts the bearer token in %#v debug representations. +func (t BearerToken) GoString() string { + return `auth.BearerToken("[REDACTED_TOKEN]")` +} + +// MarshalJSON redacts the bearer token during JSON serialization. +func (t BearerToken) MarshalJSON() ([]byte, error) { + return []byte(`"[REDACTED_TOKEN]"`), nil +} + +// LogValue implements slog.LogValuer. +func (t BearerToken) LogValue() slog.Value { + return slog.StringValue("[REDACTED_TOKEN]") +} diff --git a/packages/sdk-go/client.go b/packages/sdk-go/client.go new file mode 100644 index 0000000..88b3bb1 --- /dev/null +++ b/packages/sdk-go/client.go @@ -0,0 +1,237 @@ +package gemini + +import ( + "fmt" + "log/slog" + "net/url" + "strings" + + "github.com/gemini/developer-platform/packages/sdk-go/services" + "github.com/gemini/developer-platform/packages/sdk-go/transport" + "github.com/gemini/developer-platform/packages/sdk-go/websocket" +) + +// Client is the primary entrypoint to the Gemini Go SDK. +type Client struct { + config *clientConfig + + MarketData *services.MarketDataService + Trading *services.TradingService + Margin *services.MarginService + Perpetuals *services.PerpetualsService + Account *services.AccountService + Staking *services.StakingService + Transfers *services.TransfersService + Clearing *services.ClearingService + Predictions *services.PredictionsService + Heartbeat *services.HeartbeatService + + publicWS *websocket.Client + privateWS *websocket.Client +} + +// NewClient initializes a new Gemini SDK Client with functional options. +func NewClient(opts ...Option) *Client { + cfg := newClientConfig(opts...) + return newClientFromConfig(cfg) +} + +// NewClientWithError initializes a new Gemini SDK Client and returns an error +// when its options are invalid. Use this constructor when configuration errors +// must be detected before any request or WebSocket connection is attempted. +func NewClientWithError(opts ...Option) (*Client, error) { + cfg := newClientConfig(opts...) + if cfg.configErr != nil { + return nil, cfg.configErr + } + return newClientFromConfig(cfg), nil +} + +func newClientConfig(opts ...Option) *clientConfig { + cfg := &clientConfig{ + env: Production, + restURL: endpoints[Production].REST, + wsURL: endpoints[Production].WebSocket, + retry: transport.DefaultRetryPolicy(), + logger: slog.Default(), + userAgent: "gemini-go/0.1.0", + ownsHTTPClient: true, + } + + for _, opt := range opts { + if opt != nil { + opt(cfg) + } + } + validateClientConfig(cfg) + return cfg +} + +func validateClientConfig(cfg *clientConfig) { + if cfg.configErr != nil { + return + } + if validator, ok := cfg.auth.(interface{ Validate() error }); ok { + if err := validator.Validate(); err != nil { + cfg.configErr = err + return + } + } + if err := validateEndpointURL(cfg.restURL, "REST", "https"); err != nil { + cfg.configErr = err + return + } + if err := validateEndpointURL(cfg.wsURL, "WebSocket", "wss"); err != nil { + cfg.configErr = err + } +} + +func validateEndpointURL(raw, name string, schemes ...string) error { + parsed, err := url.Parse(strings.TrimSpace(raw)) + if err != nil { + return fmt.Errorf("%w: %s endpoint: %v", ErrInvalidEndpointURL, name, err) + } + if parsed.Host == "" { + return fmt.Errorf("%w: %s endpoint must include a host", ErrInvalidEndpointURL, name) + } + if parsed.User != nil { + return fmt.Errorf("%w: %s endpoint must not include userinfo", ErrInvalidEndpointURL, name) + } + if parsed.RawQuery != "" || parsed.ForceQuery || parsed.Fragment != "" { + return fmt.Errorf("%w: %s endpoint must not include a query or fragment", ErrInvalidEndpointURL, name) + } + for _, scheme := range schemes { + if strings.EqualFold(parsed.Scheme, scheme) { + return nil + } + } + return fmt.Errorf("%w: %s endpoint must use %s", ErrInvalidEndpointURL, name, strings.Join(schemes, " or ")) +} + +// PublicWebSocket returns the dedicated unauthenticated WebSocket client for public market data streams. +func (c *Client) PublicWebSocket() *websocket.Client { + return c.publicWS +} + +// PrivateWebSocket returns the dedicated authenticated WebSocket client for account/order feeds. +func (c *Client) PrivateWebSocket() *websocket.Client { + return c.privateWS +} + +// NewQuoteReconciler creates a declarative order book quoting reconciler for a symbol. +// It uses the authenticated PrivateWebSocket connection to receive low-latency order updates. +func (c *Client) NewQuoteReconciler(symbol string, opts ...services.ReconcilerOption) *services.QuoteReconciler { + return services.NewQuoteReconciler(c.Trading, c.privateWS, symbol, opts...) +} + +// WithOptions creates a copy of the client with modified configuration options. +// SDK-owned HTTP transports are not shared between the two clients; caller- +// supplied HTTP clients remain shared and caller-owned. +func (c *Client) WithOptions(opts ...Option) *Client { + newCfg := *c.config + newCfg.configErr = nil + if c.config.ownsHTTPClient { + // A default client owns its transport. Let newClientFromConfig create a + // fresh client so closing either facade cannot close idle connections + // belonging to the other facade. + newCfg.httpClient = nil + newCfg.ownsHTTPClient = true + } + // Shallow copy slices to prevent mutating original client's hooks + if len(c.config.hooks) > 0 { + newCfg.hooks = make([]transport.Hook, len(c.config.hooks)) + copy(newCfg.hooks, c.config.hooks) + } + + for _, opt := range opts { + if opt != nil { + opt(&newCfg) + } + } + validateClientConfig(&newCfg) + + return newClientFromConfig(&newCfg) +} + +func newClientFromConfig(cfg *clientConfig) *Client { + if cfg.httpClient == nil { + cfg.httpClient = transport.DefaultHTTPClient() + cfg.ownsHTTPClient = true + } + + privateConfigErr := cfg.configErr + if privateConfigErr == nil && cfg.auth == nil { + privateConfigErr = transport.ErrAuthenticationRequired + } + transportClient := transport.NewClient( + transport.WithHTTPClient(cfg.httpClient), + transport.WithAuth(cfg.auth), + transport.WithConfigurationError(privateConfigErr), + transport.WithRetryPolicy(cfg.retry), + transport.WithLogger(cfg.logger), + transport.WithUserAgent(cfg.userAgent), + transport.WithHooks(cfg.hooks...), + ) + publicTransport := transport.NewClient( + transport.WithHTTPClient(cfg.httpClient), + transport.WithConfigurationError(cfg.configErr), + transport.WithRetryPolicy(cfg.retry), + transport.WithLogger(cfg.logger), + transport.WithUserAgent(cfg.userAgent), + transport.WithHooks(cfg.hooks...), + ) + + publicWSOptions := []websocket.ClientOption{ + websocket.WithDialer(cfg.wsDialer), + websocket.WithClientLogger(cfg.logger), + websocket.WithConfigurationError(cfg.configErr), + websocket.WithSnapshot(-1), + websocket.WithIsolatedPartialSnapshots(), + } + publicWS := websocket.NewPublicClient(cfg.wsURL, publicWSOptions...) + + privateWS := websocket.NewPrivateClient( + cfg.wsURL, + cfg.auth, + websocket.WithDialer(cfg.wsDialer), + websocket.WithClientLogger(cfg.logger), + websocket.WithConfigurationError(privateConfigErr), + ) + + return &Client{ + config: cfg, + MarketData: services.NewMarketDataService(publicTransport, cfg.restURL), + Trading: services.NewTradingService(transportClient, cfg.restURL), + Margin: services.NewMarginService(transportClient, cfg.restURL), + Perpetuals: services.NewPerpetualsServiceWithPublicClient(transportClient, publicTransport, cfg.restURL), + Account: services.NewAccountService(transportClient, cfg.restURL), + Staking: services.NewStakingServiceWithPublicClient(transportClient, publicTransport, cfg.restURL), + Transfers: services.NewTransfersService(transportClient, cfg.restURL), + Clearing: services.NewClearingService(transportClient, cfg.restURL), + Predictions: services.NewPredictionsServiceWithPublicClient(transportClient, publicTransport, cfg.restURL), + Heartbeat: services.NewHeartbeatService(transportClient, cfg.restURL), + publicWS: publicWS, + privateWS: privateWS, + } +} + +// Close gracefully closes active WebSocket connections and releases idle HTTP +// connections only for the HTTP client created by the SDK. A client supplied +// with WithHTTPClient remains owned by the caller. +func (c *Client) Close() error { + var wsErr error + if c.publicWS != nil { + if err := c.publicWS.Close(); err != nil && wsErr == nil { + wsErr = err + } + } + if c.privateWS != nil && c.privateWS != c.publicWS { + if err := c.privateWS.Close(); err != nil && wsErr == nil { + wsErr = err + } + } + if c.config != nil && c.config.ownsHTTPClient && c.config.httpClient != nil { + c.config.httpClient.CloseIdleConnections() + } + return wsErr +} diff --git a/packages/sdk-go/client_internal_test.go b/packages/sdk-go/client_internal_test.go new file mode 100644 index 0000000..83ddf92 --- /dev/null +++ b/packages/sdk-go/client_internal_test.go @@ -0,0 +1,52 @@ +package gemini + +import ( + "testing" + + "github.com/gemini/developer-platform/packages/sdk-go/auth" +) + +func TestWithOptionsDoesNotShareSDKOwnedHTTPClient(t *testing.T) { + base := NewClient() + clone := base.WithOptions(WithCustomRESTURL("https://custom.gemini.local")) + defer base.Close() + defer clone.Close() + + if base.config.httpClient == clone.config.httpClient { + t.Fatal("WithOptions shared an SDK-owned HTTP client") + } + if !base.config.ownsHTTPClient || !clone.config.ownsHTTPClient { + t.Fatal("expected both clients to own their independent default HTTP clients") + } +} + +func TestWithOptionsRecoversFromCorrectedConfiguration(t *testing.T) { + tests := map[string]struct { + base *Client + opts []Option + }{ + "REST endpoint": { + base: NewClient(WithCustomRESTURL("://invalid")), + opts: []Option{WithCustomRESTURL("https://api.gemini.com")}, + }, + "authentication": { + base: NewClient(WithAuth(auth.NewHMAC("", "secret"))), + opts: []Option{WithAuth(auth.NewHMAC("key", "secret"))}, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + defer test.base.Close() + if test.base.config.configErr == nil { + t.Fatal("expected base client configuration error") + } + + clone := test.base.WithOptions(test.opts...) + defer clone.Close() + if err := clone.config.configErr; err != nil { + t.Fatalf("corrected client retained configuration error: %v", err) + } + }) + } +} diff --git a/packages/sdk-go/client_test.go b/packages/sdk-go/client_test.go new file mode 100644 index 0000000..6b975a8 --- /dev/null +++ b/packages/sdk-go/client_test.go @@ -0,0 +1,482 @@ +package gemini_test + +import ( + "context" + "errors" + "net/http" + "net/http/httptest" + "sync/atomic" + "testing" + + "github.com/gemini/developer-platform/packages/sdk-go" + "github.com/gemini/developer-platform/packages/sdk-go/auth" + "github.com/gemini/developer-platform/packages/sdk-go/geminitest" + "github.com/gemini/developer-platform/packages/sdk-go/generated/account" + "github.com/gemini/developer-platform/packages/sdk-go/generated/predictions" + "github.com/gemini/developer-platform/packages/sdk-go/generated/trading" + "github.com/gemini/developer-platform/packages/sdk-go/transport" + "github.com/gemini/developer-platform/packages/sdk-go/websocket" +) + +type trackingRoundTripper struct { + closeIdleCalls atomic.Int32 + roundTrips atomic.Int32 +} + +func (t *trackingRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { + t.roundTrips.Add(1) + return nil, errors.New("tracking transport: RoundTrip not expected") +} + +func (t *trackingRoundTripper) CloseIdleConnections() { + t.closeIdleCalls.Add(1) +} + +func TestClient_InvalidEnvironmentFailsClosed(t *testing.T) { + _, err := gemini.NewClientWithError(gemini.WithEnvironment(gemini.Environment("sandbxo"))) + if !errors.Is(err, gemini.ErrInvalidEnvironment) { + t.Fatalf("expected invalid environment error, got %v", err) + } + + client := gemini.NewClient(gemini.WithEnvironment(gemini.Environment("sandbxo"))) + defer client.Close() + if _, err := client.MarketData.GetSymbols(context.Background()); !errors.Is(err, gemini.ErrInvalidEnvironment) { + t.Fatalf("expected invalid environment request error, got %v", err) + } + + validClient, err := gemini.NewClientWithError( + gemini.WithEnvironment(gemini.Environment("sandbxo")), + gemini.WithEnvironment(gemini.Sandbox), + ) + if err != nil { + t.Fatalf("expected a later valid environment option to recover configuration, got %v", err) + } + defer validClient.Close() +} + +func TestClient_InvalidCustomEndpointsFailEarly(t *testing.T) { + if _, err := gemini.NewClientWithError(gemini.WithCustomRESTURL("api.gemini.local")); !errors.Is(err, gemini.ErrInvalidEndpointURL) { + t.Fatalf("expected invalid REST endpoint error, got %v", err) + } + if _, err := gemini.NewClientWithError(gemini.WithCustomWSURL("https://ws.gemini.local")); !errors.Is(err, gemini.ErrInvalidEndpointURL) { + t.Fatalf("expected invalid WebSocket endpoint error, got %v", err) + } + + for _, endpoint := range []string{ + "http://api.gemini.local", + "https://api.gemini.local?tenant=sandbox", + "https://api.gemini.local#fragment", + "https://api.gemini.local?", + "https://user:password@api.gemini.local", + } { + if _, err := gemini.NewClientWithError(gemini.WithCustomRESTURL(endpoint)); !errors.Is(err, gemini.ErrInvalidEndpointURL) { + t.Errorf("REST endpoint %q error = %v, want ErrInvalidEndpointURL", endpoint, err) + } + } + for _, endpoint := range []string{ + "ws://ws.gemini.local", + "wss://ws.gemini.local?tenant=sandbox", + "wss://ws.gemini.local#fragment", + "wss://ws.gemini.local?", + "wss://user:password@ws.gemini.local", + } { + if _, err := gemini.NewClientWithError(gemini.WithCustomWSURL(endpoint)); !errors.Is(err, gemini.ErrInvalidEndpointURL) { + t.Errorf("WebSocket endpoint %q error = %v, want ErrInvalidEndpointURL", endpoint, err) + } + } +} + +func TestClient_InvalidBearerConfigurationFailsEarly(t *testing.T) { + _, err := gemini.NewClientWithError(gemini.WithTokenSource(nil)) + if !errors.Is(err, gemini.ErrInvalidTokenSource) { + t.Fatalf("expected ErrInvalidTokenSource, got %v", err) + } + + client := gemini.NewClient(gemini.WithBearerToken("")) + defer client.Close() + if _, err := client.Account.GetAccount(context.Background(), nil); !errors.Is(err, gemini.ErrInvalidTokenSource) { + t.Fatalf("expected invalid bearer configuration to fail requests, got %v", err) + } + + if _, err := gemini.NewClientWithError(gemini.WithAPIKey("", "secret")); !errors.Is(err, gemini.ErrInvalidHMACCredentials) { + t.Fatalf("expected empty HMAC key to fail early, got %v", err) + } + if _, err := gemini.NewClientWithError(gemini.WithAPIKey("key", "")); !errors.Is(err, gemini.ErrInvalidHMACCredentials) { + t.Fatalf("expected empty HMAC secret to fail early, got %v", err) + } +} + +func TestClient_PrivateRESTRequiresAuthenticationBeforeNetwork(t *testing.T) { + tracker := &trackingRoundTripper{} + client := gemini.NewClient( + gemini.WithCustomRESTURL("https://api.gemini.test"), + gemini.WithHTTPClient(&http.Client{Transport: tracker}), + ) + defer client.Close() + + _, err := client.Account.GetAccount(context.Background(), nil) + if !errors.Is(err, gemini.ErrAuthenticationRequired) { + t.Fatalf("expected ErrAuthenticationRequired, got %v", err) + } + if got := tracker.roundTrips.Load(); got != 0 { + t.Fatalf("private REST request reached the network %d time(s)", got) + } +} + +func TestClient_PredictionsSplitsPublicAndPrivateREST(t *testing.T) { + var privateHits atomic.Int32 + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/v1/prediction-markets/events": + _, _ = w.Write([]byte(`{"data":[]}`)) + case "/v1/fundingamount/BTCUSD": + _, _ = w.Write([]byte(`{}`)) + case "/v1/nextfundingtimestamp/BTCUSD": + _, _ = w.Write([]byte(`0`)) + case "/v1/staking/rates": + _, _ = w.Write([]byte(`{}`)) + default: + privateHits.Add(1) + http.NotFound(w, r) + } + })) + defer server.Close() + + client := gemini.NewClient( + gemini.WithCustomRESTURL(server.URL), + gemini.WithHTTPClient(server.Client()), + ) + defer client.Close() + + if _, err := client.Predictions.GetEvents(context.Background(), nil); err != nil { + t.Fatalf("public prediction endpoint should work without auth: %v", err) + } + if _, err := client.Perpetuals.GetFundingAmount(context.Background(), "BTCUSD"); err != nil { + t.Fatalf("public perpetual funding endpoint should work without auth: %v", err) + } + if _, err := client.Perpetuals.GetNextFundingTimestamp(context.Background(), "BTCUSD"); err != nil { + t.Fatalf("public perpetual funding timestamp endpoint should work without auth: %v", err) + } + if _, err := client.Staking.GetStakingRates(context.Background()); err != nil { + t.Fatalf("public staking rates endpoint should work without auth: %v", err) + } + if _, err := client.Predictions.NewOrder(context.Background(), &predictions.OrderRequest{}); !errors.Is(err, gemini.ErrAuthenticationRequired) { + t.Fatalf("private prediction endpoint should fail closed without auth, got %v", err) + } + if got := privateHits.Load(); got != 0 { + t.Fatalf("private prediction request reached the network %d time(s)", got) + } +} + +func TestClient_EndToEnd(t *testing.T) { + apiKey := "test-key-123" + apiSecret := "test-secret-456" + + server := geminitest.NewMockServer(apiKey, apiSecret) + defer server.Close() + + client := gemini.NewClient( + gemini.WithCustomRESTURL(server.URL()), + gemini.WithHTTPClient(server.HTTPClient()), + gemini.WithAPIKey(apiKey, apiSecret), + ) + + ctx := context.Background() + + // 1. Public Market Data + symbols, err := client.MarketData.GetSymbols(ctx) + if err != nil { + t.Fatalf("failed getting symbols: %v", err) + } + if len(symbols) != 3 || symbols[0] != "btcusd" { + t.Fatalf("unexpected symbols response: %v", symbols) + } + + ticker, err := client.MarketData.GetTicker(ctx, "btcusd") + if err != nil { + t.Fatalf("failed getting ticker: %v", err) + } + if ticker.Bid == nil || *ticker.Bid != "65000.00" { + t.Fatalf("unexpected ticker response: %+v", ticker) + } + + book, err := client.MarketData.GetOrderBook(ctx, "btcusd", 10, 10) + if err != nil { + t.Fatalf("failed getting order book: %v", err) + } + if book.Bids == nil || len(*book.Bids) == 0 || (*book.Bids)[0].Price == nil || *(*book.Bids)[0].Price != "65000.00" { + t.Fatalf("unexpected book response: %+v", book) + } + + // 2. Private Authenticated Trading + newOrderReq := &trading.NewOrderRequest{ + Symbol: "btcusd", + Amount: "1.5", + Price: "65000.00", + Side: trading.NewOrderRequestSideBuy, + Type: trading.NewOrderRequestTypeExchangeLimit, + } + + orderRes, err := client.Trading.NewOrder(ctx, newOrderReq) + if err != nil { + t.Fatalf("failed placing new order: %v", err) + } + if orderRes.Symbol == nil || *orderRes.Symbol != "btcusd" || orderRes.RemainingAmount == nil || *orderRes.RemainingAmount != "1.5" { + t.Fatalf("unexpected order result: %+v", orderRes) + } + + // 3. Private Account Balances + balances, err := client.Account.GetBalances(ctx, &account.GetAvailableBalancesJSONBody{Account: "primary"}) + if err != nil { + t.Fatalf("failed getting balances: %v", err) + } + if len(balances) != 2 || balances[0].Currency == nil || *balances[0].Currency != "USD" { + t.Fatalf("unexpected balances: %+v", balances) + } + + // 4. Prediction Markets Terms Gating + predReq := &predictions.OrderRequest{ + OrderType: predictions.OrderTypeLimit, + Outcome: predictions.Yes, + Price: "0.50", + Quantity: "100", + Side: predictions.OrderSideBuy, + Symbol: "presidential-2028", + } + _, err = client.Predictions.NewOrder(ctx, predReq) + if !errors.Is(err, transport.ErrAcceptTermsRequired) { + t.Fatalf("expected ErrAcceptTermsRequired, got %v", err) + } + + // Accept terms and retry + if _, err := client.Predictions.AcceptTerms(ctx); err != nil { + t.Fatalf("failed accepting terms: %v", err) + } + + // Post-accept gating: order submission must succeed now + predOrder, err := client.Predictions.NewOrder(ctx, predReq) + if err != nil { + t.Fatalf("failed placing prediction order after terms accepted: %v", err) + } + if predOrder.OrderId == nil || *predOrder.OrderId != 12345 { + t.Fatalf("unexpected prediction order result: %+v", predOrder) + } + + // 5. Staking Service + stkBalances, err := client.Staking.GetStakingBalances(ctx, nil) + if err != nil || len(stkBalances) != 1 { + t.Fatalf("failed getting staking balances: %v", err) + } + + // 6. Transfers Service + transfers, err := client.Transfers.GetTransfers(ctx, nil) + if err != nil || len(transfers) != 1 { + t.Fatalf("failed getting transfers: %v", err) + } + + // 7. WebSocket missing dialer returns actionable ErrNoDialerConfigured + ws := client.PublicWebSocket() + _, wsErr := ws.SubscribeDepth(ctx, "btcusd") + if !errors.Is(wsErr, websocket.ErrNoDialerConfigured) { + t.Fatalf("expected ErrNoDialerConfigured when no dialer is set, got %v", wsErr) + } +} + +func TestClient_OAuthStaticBearer(t *testing.T) { + bearerToken := "oauth-bearer-token-12345" + server := geminitest.NewMockOAuthServer(bearerToken) + defer server.Close() + + client := gemini.NewClient( + gemini.WithCustomRESTURL(server.URL()), + gemini.WithHTTPClient(server.HTTPClient()), + gemini.WithBearerToken(bearerToken), + ) + + ctx := context.Background() + + // 1. Authenticated Account Balances via Bearer Token + balances, err := client.Account.GetBalances(ctx, &account.GetAvailableBalancesJSONBody{Account: "primary"}) + if err != nil { + t.Fatalf("failed getting balances via OAuth: %v", err) + } + if len(balances) != 2 || balances[0].Currency == nil || *balances[0].Currency != "USD" { + t.Fatalf("unexpected balances: %+v", balances) + } + + // 2. Authenticated Order Placement via Bearer Token + order, err := client.Trading.NewOrder(ctx, &trading.NewOrderRequest{ + Symbol: "btcusd", + Amount: "2.0", + Price: "64000.00", + Side: trading.NewOrderRequestSideBuy, + Type: trading.NewOrderRequestTypeExchangeLimit, + }) + if err != nil { + t.Fatalf("failed placing order via OAuth: %v", err) + } + if order.Symbol == nil || *order.Symbol != "btcusd" { + t.Fatalf("unexpected order: %+v", order) + } + + // 3. OAuth token revocation uses the bearer token making the request. + revoked, err := client.Account.RevokeOAuthToken(ctx) + if err != nil || revoked == nil || revoked.Message != "token revoked" { + t.Fatalf("failed revoking OAuth token: %v", err) + } +} + +func TestClient_OAuthDynamicTokenSource(t *testing.T) { + currentOAuthToken := "token-gen-1" + server := geminitest.NewMockOAuthServer("token-gen-2") // server expects token-gen-2 + defer server.Close() + + tokenFetcher := auth.TokenFunc(func(ctx context.Context) (string, error) { + return currentOAuthToken, nil + }) + + client := gemini.NewClient( + gemini.WithCustomRESTURL(server.URL()), + gemini.WithHTTPClient(server.HTTPClient()), + gemini.WithTokenSource(tokenFetcher), + ) + + ctx := context.Background() + + // Initial call with token-gen-1 must fail with 401 Unauthorized + _, err := client.Account.GetBalances(ctx, &account.GetAvailableBalancesJSONBody{Account: "primary"}) + if err == nil { + t.Fatal("expected unauthorized error with stale token, got nil") + } + + // Dynamic token renewal + currentOAuthToken = "token-gen-2" + + // Subsequent call automatically uses renewed token and succeeds + balances, err := client.Account.GetBalances(ctx, &account.GetAvailableBalancesJSONBody{Account: "primary"}) + if err != nil { + t.Fatalf("expected success with refreshed token, got %v", err) + } + if len(balances) != 2 { + t.Fatalf("unexpected balances length: %d", len(balances)) + } +} + +func TestClient_ErrorPredicates(t *testing.T) { + if !gemini.IsRateLimit(gemini.ErrRateLimited) { + t.Error("expected IsRateLimit(ErrRateLimited) to be true") + } + if !gemini.IsInsufficientFunds(gemini.ErrInsufficientFunds) { + t.Error("expected IsInsufficientFunds(ErrInsufficientFunds) to be true") + } + if !gemini.IsAuthError(gemini.ErrInvalidSignature) || !gemini.IsAuthError(gemini.ErrInvalidNonce) || !gemini.IsAuthError(gemini.ErrUnauthorized) { + t.Error("expected IsAuthError to be true for auth errors") + } + if !gemini.IsNotFound(gemini.ErrOrderNotFound) || !gemini.IsNotFound(gemini.ErrNotFound) { + t.Error("expected IsNotFound to be true for not found errors") + } + if !gemini.IsBadRequest(gemini.ErrBadRequest) { + t.Error("expected IsBadRequest(ErrBadRequest) to be true") + } + if !gemini.IsPermissionDenied(gemini.ErrPermissionDenied) || !gemini.IsPermissionDenied(gemini.ErrMissingRole) { + t.Error("expected IsPermissionDenied to be true") + } + if !gemini.IsConflict(gemini.ErrConflict) { + t.Error("expected IsConflict(ErrConflict) to be true") + } + if !gemini.IsInternalServerError(gemini.ErrInternalServer) { + t.Error("expected IsInternalServerError(ErrInternalServer) to be true") + } + if gemini.IsRateLimit(gemini.ErrOrderNotFound) { + t.Error("expected IsRateLimit(ErrOrderNotFound) to be false") + } +} + +func TestClient_RootAliases(t *testing.T) { + d := gemini.MustDecimal("65000.50") + if d.String() != "65000.5" { + t.Errorf("unexpected decimal: %s", d.String()) + } + + q := gemini.DesiredQuote{ + Side: "buy", + Price: d, + Amount: gemini.MustDecimal("1.0"), + } + if q.Side != "buy" || q.Price.String() != "65000.5" { + t.Errorf("unexpected quote alias struct: %+v", q) + } + + secret := gemini.APISecret("test-secret-root-alias") + b64Payload := "eyJyZXF1ZXN0IjoiL3YxL29yZGVycyIsIm5vbmNlIjoiOTg3NjU0MzIxIn0=" + sig := auth.NewHMAC("key", secret).Sign([]byte(b64Payload)) + if !gemini.VerifySignature(secret, b64Payload, sig) { + t.Error("expected VerifySignature root alias to verify successfully") + } +} + +func TestClient_WithOptionsAndClose(t *testing.T) { + baseClient := gemini.NewClient( + gemini.WithEnvironment(gemini.Sandbox), + gemini.WithAPIKey("base-key-12345", "base-secret-12345"), + ) + + // Clone client with new URL and sandbox options + scopedClient := baseClient.WithOptions( + gemini.WithCustomRESTURL("https://custom.gemini.local"), + ) + + if scopedClient == baseClient { + t.Fatal("expected WithOptions to return a new client instance") + } + if scopedClient.MarketData == nil || scopedClient.Trading == nil { + t.Fatal("expected services to be initialized on cloned client") + } + + if err := baseClient.Close(); err != nil { + t.Fatalf("unexpected error closing base client: %v", err) + } + if err := scopedClient.Close(); err != nil { + t.Fatalf("unexpected error closing scoped client: %v", err) + } +} + +func TestClient_DoesNotCloseCallerOwnedHTTPClient(t *testing.T) { + transport := &trackingRoundTripper{} + httpClient := &http.Client{Transport: transport} + client := gemini.NewClient(gemini.WithHTTPClient(httpClient)) + + if err := client.Close(); err != nil { + t.Fatalf("unexpected error closing client: %v", err) + } + if got := transport.closeIdleCalls.Load(); got != 0 { + t.Fatalf("expected caller-owned transport to remain open, got %d CloseIdleConnections calls", got) + } +} + +func TestClient_PublicAndPrivateWebSocketConnections(t *testing.T) { + client := gemini.NewClient( + gemini.WithAPIKey("key-123", "secret-456"), + ) + defer client.Close() + + pubWS := client.PublicWebSocket() + privWS := client.PrivateWebSocket() + + if pubWS == nil { + t.Fatal("expected PublicWebSocket to be non-nil") + } + if privWS == nil { + t.Fatal("expected PrivateWebSocket to be non-nil") + } + if pubWS == privWS { + t.Fatal("expected PublicWebSocket and PrivateWebSocket to be distinct connection instances") + } + // Unauthenticated client + anonClient := gemini.NewClient() + defer anonClient.Close() + + if _, err := anonClient.PrivateWebSocket().SubscribeOrderEvents(context.Background()); !errors.Is(err, gemini.ErrAuthenticationRequired) { + t.Fatalf("expected ErrAuthenticationRequired on anonymous private client, got %v", err) + } +} diff --git a/packages/sdk-go/cmd/demo/go.mod b/packages/sdk-go/cmd/demo/go.mod new file mode 100644 index 0000000..c0b7b3b --- /dev/null +++ b/packages/sdk-go/cmd/demo/go.mod @@ -0,0 +1,14 @@ +module github.com/gemini/developer-platform/packages/sdk-go/cmd/demo + +go 1.23.0 + +replace github.com/gemini/developer-platform/packages/sdk-go => ../.. + +replace github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla => ../../websocket/gorilla + +require ( + github.com/gemini/developer-platform/packages/sdk-go v0.1.0 + github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla v0.1.0 +) + +require github.com/gorilla/websocket v1.5.3 // indirect diff --git a/packages/sdk-go/cmd/demo/go.sum b/packages/sdk-go/cmd/demo/go.sum new file mode 100644 index 0000000..25a9fc4 --- /dev/null +++ b/packages/sdk-go/cmd/demo/go.sum @@ -0,0 +1,2 @@ +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= diff --git a/packages/sdk-go/cmd/demo/main.go b/packages/sdk-go/cmd/demo/main.go new file mode 100644 index 0000000..0c840df --- /dev/null +++ b/packages/sdk-go/cmd/demo/main.go @@ -0,0 +1,432 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "log/slog" + "net/http" + "os" + "os/exec" + "runtime" + "strings" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go" + "github.com/gemini/developer-platform/packages/sdk-go/auth" + "github.com/gemini/developer-platform/packages/sdk-go/geminitest" + "github.com/gemini/developer-platform/packages/sdk-go/generated/account" + "github.com/gemini/developer-platform/packages/sdk-go/generated/predictions" + geminioauth "github.com/gemini/developer-platform/packages/sdk-go/oauth" + "github.com/gemini/developer-platform/packages/sdk-go/transport" + "github.com/gemini/developer-platform/packages/sdk-go/websocket" + "github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla" + "github.com/gemini/developer-platform/packages/sdk-go/websocket/orderbook" +) + +const ( + demoRFQSubmitConfirmation = "I_UNDERSTAND_THIS_SUBMITS_A_LIVE_RFQ_QUOTE" + demoCLIClientID = "6a03a47b-1bb4-491a-b0a7-35ad17473e71" +) + +func main() { + logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) + slog.SetDefault(logger) + + fmt.Println("==================================================") + fmt.Println("🚀 Gemini Official Go SDK Local Validation Suite") + fmt.Println("==================================================") + + ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second) + defer cancel() + + // 1. Initialize Client against Production endpoints with pluggable Gorilla dialer and latency tracing + clientOptions := []gemini.Option{ + gemini.WithEnvironment(gemini.Production), + gemini.WithWebSocketDialer(gorilla.NewDialer()), + gemini.WithLogger(logger), + gemini.WithTraceHook(func(req *http.Request, trace transport.LatencyBreakdown, err error) { + if trace.ConnectionReused { + fmt.Printf(" [Trace: %v (Reused Socket, TTFB: %v)]\n", trace.TotalDuration.Round(time.Microsecond), trace.TimeToFirstByte.Round(time.Microsecond)) + } else { + fmt.Printf(" [Trace: %v (New Socket, TLS: %v, TTFB: %v)]\n", trace.TotalDuration.Round(time.Microsecond), trace.TLSHandshake.Round(time.Microsecond), trace.TimeToFirstByte.Round(time.Microsecond)) + } + }), + } + bearerToken := strings.TrimSpace(os.Getenv("GEMINI_ACCESS_TOKEN")) + oauthLoginEnabled := os.Getenv("GEMINI_DEMO_OAUTH_LOGIN") == "1" + rfqSubmitEnabled := os.Getenv("GEMINI_DEMO_RFQ_SUBMIT") == "1" + rfqPrice := strings.TrimSpace(os.Getenv("GEMINI_DEMO_RFQ_PRICE")) + rfqQuantity := strings.TrimSpace(os.Getenv("GEMINI_DEMO_RFQ_QUANTITY")) + if bearerToken != "" && oauthLoginEnabled { + log.Fatal("set only one of GEMINI_ACCESS_TOKEN or GEMINI_DEMO_OAUTH_LOGIN=1") + } + if rfqSubmitEnabled { + if os.Getenv("GEMINI_DEMO_RFQ_CONFIRM") != demoRFQSubmitConfirmation { + log.Fatalf("RFQ submit mode requires GEMINI_DEMO_RFQ_CONFIRM=%s", demoRFQSubmitConfirmation) + } + if rfqPrice == "" || rfqQuantity == "" { + log.Fatal("RFQ submit mode requires GEMINI_DEMO_RFQ_PRICE and GEMINI_DEMO_RFQ_QUANTITY") + } + fmt.Printf("⚠️ [RFQ] Submit mode armed for price=%s quantity=%s; it will submit at most one live quote\n", rfqPrice, rfqQuantity) + } + authConfigured := bearerToken != "" + if bearerToken != "" { + clientOptions = append(clientOptions, gemini.WithBearerToken(bearerToken)) + fmt.Println("🔑 [OAuth 2.0] Production bearer token configured for private WebSocket validation") + } + if oauthLoginEnabled { + clientID := strings.TrimSpace(os.Getenv("GEMINI_OAUTH_CLIENT_ID")) + if clientID == "" { + clientID = demoCLIClientID + } + oauthConfig := geminioauth.Config{ + ClientID: clientID, + ClientSecret: strings.TrimSpace(os.Getenv("GEMINI_OAUTH_CLIENT_SECRET")), + Endpoint: geminioauth.Endpoint{ + AuthURL: "https://exchange.gemini.com/auth", + TokenURL: "https://exchange.gemini.com/auth/token", + }, + RedirectURL: "http://localhost:8787/callback", + Scopes: demoOAuthScopes(rfqSubmitEnabled), + } + fmt.Println("🔐 [OAuth 2.0] Starting CLI-compatible PKCE login (credentials remain in memory)...") + token, err := oauthConfig.Login(ctx, openBrowser) + if err != nil { + log.Fatalf("OAuth PKCE login failed: %v\n", err) + } + source, err := geminioauth.NewTokenSource(oauthConfig, *token) + if err != nil { + log.Fatalf("OAuth token source setup failed: %v\n", err) + } + clientOptions = append(clientOptions, gemini.WithTokenSource(source)) + authConfigured = true + fmt.Println(" ✅ OAuth PKCE authorization completed; bearer token source configured") + } + if rfqSubmitEnabled { + if !authConfigured { + log.Fatal("RFQ submit mode requires GEMINI_ACCESS_TOKEN or GEMINI_DEMO_OAUTH_LOGIN=1") + } + } + client := gemini.NewClient(clientOptions...) + defer client.Close() + + // 2. REST API: GetSymbols + fmt.Print("📡 [REST] Fetching active market symbols...") + symbols, err := client.MarketData.GetSymbols(ctx) + if err != nil { + log.Fatalf("FAILED: %v\n", err) + } + fmt.Printf(" ✅ Fetched %d active market symbols\n", len(symbols)) + + // 3. REST API: GetTicker + fmt.Print("📊 [REST] Fetching live BTCUSD ticker...") + ticker, err := client.MarketData.GetTicker(ctx, "BTCUSD") + if err != nil { + log.Fatalf("FAILED: %v\n", err) + } + fmt.Printf("✅ SUCCESS!\n • Last Price: $%s\n • Best Bid: $%s\n • Best Ask: $%s\n", + gemini.Val(ticker.Last), gemini.Val(ticker.Bid), gemini.Val(ticker.Ask)) + + // 4. REST API: Prediction Markets Contracts & Terms + fmt.Print("🔮 [REST] Fetching Prediction Markets Terms & Live Events...") + terms, termsErr := client.Predictions.GetTerms(ctx) + if termsErr == nil { + fmt.Printf(" ✅ Terms Available (v%d: %s)\n", terms.Version, terms.TermsType) + } + limit := predictions.Limit(5) + events, eventsErr := client.Predictions.GetEvents(ctx, &predictions.ListEventsParams{Limit: &limit}) + if eventsErr == nil { + if events != nil && events.Data != nil && len(*events.Data) > 0 { + data := *events.Data + firstEvt := data[0] + fmt.Printf(" ✅ Fetched %d Live Prediction Events\n", len(data)) + fmt.Printf(" • Event: \"%s\" (ID: %s)\n", gemini.Val(firstEvt.Title), gemini.Val(firstEvt.Id)) + if firstEvt.Contracts != nil && len(*firstEvt.Contracts) > 0 { + contracts := *firstEvt.Contracts + fmt.Printf(" • Tradeable Contracts (%d outcomes):\n", len(contracts)) + for i, contract := range contracts { + if i >= 3 { + break + } + fmt.Printf(" [%d] Contract: %-20s | Status: %v\n", + i+1, gemini.Val(contract.InstrumentSymbol), gemini.Val(contract.MarketState)) + } + } + } else { + fmt.Println(" ✅ Prediction markets endpoint queried successfully") + } + } else { + fmt.Printf(" ℹ️ Prediction events queried: %v\n", eventsErr) + } + + // 5. REST API: Derivatives & Perpetuals Funding + fmt.Print("📈 [REST] Fetching BTC-GUSD Perpetual Funding Rates...") + funding, fundingErr := client.Perpetuals.GetFundingAmount(ctx, "btcgusdperp") + if fundingErr == nil && funding != nil { + fmt.Printf(" ✅ Current Funding: %v | Est Next: %v\n", gemini.Val(funding.Amount), gemini.Val(funding.EstimatedFundingAmount)) + } else { + fmt.Printf(" ℹ️ Perpetuals info queried: %v\n", fundingErr) + } + + // 6. Go 1.23+ iter.Seq2 Range-Over-Func Native Pagination + fmt.Print("🔄 [Iterator] Verifying Go 1.23+ iter.Seq2 range-over-func pagination...") + type mockRecord struct { + ID int + Name string + } + mockFetcher := func(ctx context.Context, offset, limit int) ([]mockRecord, bool, error) { + if offset >= 10 { + return nil, false, nil + } + var page []mockRecord + for i := 0; i < limit && offset+i < 10; i++ { + page = append(page, mockRecord{ID: offset + i + 1, Name: fmt.Sprintf("Item-%d", offset+i+1)}) + } + return page, offset+len(page) < 10, nil + } + paginator := transport.NewPaginator(ctx, 0, 4, mockFetcher) + itemCount := 0 + for item, err := range paginator { + if err != nil { + log.Fatalf("Paginator iteration error: %v\n", err) + } + itemCount++ + _ = item + } + fmt.Printf(" ✅ Iterated %d items cleanly via native Go for-range\n", itemCount) + + // 7. OAuth 2.0 Dynamic Bearer Token Verification + fmt.Print("🔑 [OAuth 2.0] Verifying dynamic OAuth TokenSource refresh & authentication...") + oauthMock := geminitest.NewMockOAuthServer("live-demo-bearer-token") + defer oauthMock.Close() + + activeToken := "initial-expired-token" + dynamicSource := auth.TokenFunc(func(ctx context.Context) (string, error) { + return activeToken, nil + }) + + oauthClient := gemini.NewClient( + gemini.WithCustomRESTURL(oauthMock.URL()), + gemini.WithHTTPClient(oauthMock.HTTPClient()), + gemini.WithTokenSource(dynamicSource), + ) + defer oauthClient.Close() + + // Simulate expired token failure + _, err = oauthClient.Account.GetBalances(ctx, &account.GetAvailableBalancesJSONBody{Account: "primary"}) + if err == nil { + log.Fatalf("expected OAuth rejection with stale token") + } + + // Refresh token dynamically + activeToken = "live-demo-bearer-token" + oauthBalances, err := oauthClient.Account.GetBalances(ctx, &account.GetAvailableBalancesJSONBody{Account: "primary"}) + if err != nil { + log.Fatalf("OAuth call with refreshed token failed: %v", err) + } + fmt.Printf(" ✅ Successfully authenticated with renewed OAuth token (%d accounts retrieved)\n", len(oauthBalances)) + + // 8. REST API: GetOrderBook + fmt.Print("📚 [REST] Fetching L2 order book snapshot (top-5)... ") + book, err := client.MarketData.GetOrderBook(ctx, "BTCUSD", 5, 5) + if err != nil { + log.Fatalf("FAILED: %v\n", err) + } + bids := gemini.Val(book.Bids) + asks := gemini.Val(book.Asks) + fmt.Printf("✅ SUCCESS! (%d bids, %d asks)\n", len(bids), len(asks)) + if len(bids) > 0 { + fmt.Printf(" • Top Bid: %s BTC @ $%s\n", gemini.Val(bids[0].Amount), gemini.Val(bids[0].Price)) + } + if len(asks) > 0 { + fmt.Printf(" • Top Ask: %s BTC @ $%s\n", gemini.Val(asks[0].Amount), gemini.Val(asks[0].Price)) + } + + // 9. WebSocket API: Dedicated Public & Private WebSocket connections + fmt.Println("\n⚡ [WebSocket] Verifying Public vs Private WebSocket connection separation...") + + // 9a. Private WebSocket Guardrails: Unauthenticated calls fail safely + privateWS := client.PrivateWebSocket() + if !authConfigured { + if _, err := privateWS.SubscribeOrderEvents(ctx); err == gemini.ErrAuthenticationRequired { + fmt.Println(" 🛡️ Private WebSocket correctly enforces authentication guard (ErrAuthenticationRequired)") + } + } else { + fmt.Println(" 🔐 Connecting authenticated Private WebSocket (bearer token not displayed)...") + if err := privateWS.Connect(ctx); err != nil { + log.Fatalf("Authenticated Private WebSocket connection failed: %v\n", err) + } + fmt.Println(" ✅ OAuth bearer private WebSocket handshake established") + } + + // 9b. Public WebSocket: High-throughput unauthenticated market data stream + fmt.Println(" 📡 Connecting dedicated Public WebSocket (wss://ws.gemini.com)...") + ws := client.PublicWebSocket() + defer ws.Close() + + if err := ws.Connect(ctx); err != nil { + log.Fatalf("Public WebSocket connection failed: %v\n", err) + } + fmt.Println(" ✅ Public Handshake Established (101 Switching Protocols)") + + fmt.Println(" 📡 Subscribing to public RFQ discovery stream (requestForQuote)...") + rfqCh, err := ws.SubscribeRFQEvents(ctx) + if err != nil { + log.Fatalf("SubscribeRFQEvents failed: %v\n", err) + } + fmt.Println(" ✅ RFQ discovery subscription established") + + fmt.Println(" 📡 Subscribing to BTCUSD Depth Feed (btcusd@depth)...") + depthCh, err := ws.SubscribeDepth(ctx, "BTCUSD") + if err != nil { + log.Fatalf("SubscribeDepth failed: %v\n", err) + } + + fmt.Println(" 📡 Subscribing to BTCUSD BookTicker Feed (btcusd@bookTicker)...") + tickerCh, err := ws.SubscribeBookTicker(ctx, "BTCUSD") + if err != nil { + log.Fatalf("SubscribeBookTicker failed: %v\n", err) + } + + // 10. Real Live L2 Order Book Engine + fmt.Println("\n📖 [OrderBook Engine] Initializing in-memory L2 LiveOrderBook...") + liveBook := orderbook.NewLiveOrderBook("BTCUSD") + if len(bids) > 0 && len(asks) > 0 { + fmt.Printf(" 📊 Initial REST OrderBook: %d bids, %d asks (Best Bid: $%s, Best Ask: $%s)\n", + len(bids), len(asks), gemini.Val(bids[0].Price), gemini.Val(asks[0].Price)) + } + + fmt.Println("\n📥 Streaming real-time market updates & synchronizing L2 Order Book...") + receivedDepth := 0 + receivedTicker := 0 + rfqObserved := false + rfqQuoteSubmitted := false + rfqWaitCompleted := false + var rfqEvents <-chan *websocket.RFQPublicEvent = rfqCh + rfqTimer := time.NewTimer(5 * time.Second) + defer rfqTimer.Stop() + var rfqWait <-chan time.Time = rfqTimer.C + + deadline := time.After(20 * time.Second) + for receivedDepth < 4 || receivedTicker < 2 { + select { + case rfq, ok := <-rfqEvents: + if !ok { + fmt.Println(" ℹ️ RFQ discovery stream closed before an event was observed") + rfqEvents = nil + rfqWait = nil + rfqWaitCompleted = true + continue + } + if !rfqObserved { + printRFQEvent(rfq) + rfqObserved = true + rfqEvents = nil + rfqWait = nil + + if rfqSubmitEnabled && rfq != nil && rfq.State == websocket.RFQStateOpen { + quote, err := privateWS.SubmitRFQQuote(ctx, websocket.RFQSubmitQuoteParams{ + RFQID: rfq.RFQID, Price: rfqPrice, Quantity: rfqQuantity, + }) + if err != nil { + log.Fatalf("SubmitRFQQuote failed: %v\n", err) + } + rfqQuoteSubmitted = true + fmt.Printf(" ✅ Submitted one live RFQ quote (RFQ ID: %s, Quote ID: %s)\n", quote.RFQID, quote.QuoteID) + } + } + + case depth, ok := <-depthCh: + if !ok { + log.Fatal("Depth channel closed unexpectedly") + } + receivedDepth++ + + if err := liveBook.IngestDiff(depth); err != nil { + log.Printf(" ⚠️ IngestDiff notification: %v\n", err) + } + if liveBook.IsLive() { + fmt.Printf(" ✅ Synchronized live orderbook at Sequence #%d\n", liveBook.Book().LastUpdateID()) + } + + bestBid, hasBid := liveBook.Book().BestBid() + bestAsk, hasAsk := liveBook.Book().BestAsk() + spread, hasSpread := liveBook.Book().Spread() + mid, _ := liveBook.Book().Mid() + + fmt.Printf(" 🟢 [Depth Event %d] Seq: %d | Changes: %d bids, %d asks\n", + receivedDepth, depth.LastUpdateID, len(depth.Bids), len(depth.Asks)) + if hasBid && hasAsk && hasSpread { + fmt.Printf(" 📊 Real-Time BBO: Bid %s BTC @ $%s | Ask %s BTC @ $%s | Spread: $%.2f | Mid: $%.2f\n", + bestBid.Amount, bestBid.Price, bestAsk.Amount, bestAsk.Price, spread, mid) + } + + case bt, ok := <-tickerCh: + if !ok { + log.Fatal("BookTicker channel closed unexpectedly") + } + receivedTicker++ + fmt.Printf(" 🔵 [BookTicker Event %d] %s | Bid: $%s (%s BTC) | Ask: $%s (%s BTC)\n", + receivedTicker, bt.Symbol, bt.BidPrice, bt.BidQty, bt.AskPrice, bt.AskQty) + + case <-rfqWait: + rfqWaitCompleted = true + rfqEvents = nil + rfqWait = nil + fmt.Println(" ℹ️ No RFQ event was published during the 5-second observation window") + + case <-deadline: + log.Fatalf("Timed out after 20s (received %d depth, %d ticker updates)\n", receivedDepth, receivedTicker) + } + } + if rfqObserved { + fmt.Println(" ✅ RFQ discovery stream delivered a live event") + } else if !rfqWaitCompleted { + fmt.Println(" ℹ️ RFQ discovery subscription was active; no event arrived during the bounded validation window") + } + if rfqSubmitEnabled && !rfqQuoteSubmitted { + fmt.Println(" ℹ️ RFQ submit mode was armed, but no open RFQ was observed; no quote was submitted") + } + + fmt.Println("\n==================================================") + fmt.Println("🎉 ALL REAL LIVE ORDER BOOK & STREAM CHECKS PASSED!") + fmt.Println("==================================================") +} + +func openBrowser(rawURL string) error { + switch runtime.GOOS { + case "darwin": + return exec.Command("open", rawURL).Start() + case "linux": + return exec.Command("xdg-open", rawURL).Start() + case "windows": + return exec.Command("rundll32", "url.dll,FileProtocolHandler", rawURL).Start() + default: + return fmt.Errorf("unsupported operating system %q; open the authorization URL manually", runtime.GOOS) + } +} + +// demoOAuthScopes returns the minimum scopes needed by the selected demo mode. +func demoOAuthScopes(rfqSubmitEnabled bool) []string { + scopes := []string{"account:read", "balances:read", "orders:read", "history:read"} + if rfqSubmitEnabled { + scopes = append(scopes, "orders:create") + } + return scopes +} + +func printRFQEvent(event *websocket.RFQPublicEvent) { + if event == nil { + fmt.Println(" ⚠️ RFQ discovery stream returned an empty event") + return + } + + payload, err := json.MarshalIndent(event, " ", " ") + if err != nil { + fmt.Printf(" ⚠️ Could not render RFQ event: %v\n", err) + return + } + fmt.Printf(" ✅ Received live RFQ event:\n%s\n", payload) +} diff --git a/packages/sdk-go/cmd/demo/main_test.go b/packages/sdk-go/cmd/demo/main_test.go new file mode 100644 index 0000000..34cb2df --- /dev/null +++ b/packages/sdk-go/cmd/demo/main_test.go @@ -0,0 +1,24 @@ +package main + +import "testing" + +func TestDemoOAuthScopesRequestWriteAccessOnlyForRFQSubmission(t *testing.T) { + readOnly := demoOAuthScopes(false) + if containsScope(readOnly, "orders:create") { + t.Fatalf("read-only demo scopes unexpectedly include orders:create: %v", readOnly) + } + + withRFQ := demoOAuthScopes(true) + if !containsScope(withRFQ, "orders:create") { + t.Fatalf("RFQ demo scopes omit orders:create: %v", withRFQ) + } +} + +func containsScope(scopes []string, want string) bool { + for _, scope := range scopes { + if scope == want { + return true + } + } + return false +} diff --git a/packages/sdk-go/doc.go b/packages/sdk-go/doc.go new file mode 100644 index 0000000..5de36c3 --- /dev/null +++ b/packages/sdk-go/doc.go @@ -0,0 +1,97 @@ +// Package gemini provides the official, zero-dependency Go SDK for the Gemini Exchange APIs. +// +// # Overview +// +// The SDK supports both REST and WebSocket APIs for high-frequency trading, market data, +// account management, margin, derivatives/perpetuals, clearing, and prediction markets. +// +// Built natively for Go 1.23+, the core SDK depends exclusively on the Go standard library, +// providing sub-microsecond in-memory order books, declarative quote reconciliation, +// automatic clock skew calibration, monotonic nonces, and resilient connection pooling. +// +// # Quick Start +// +// import "github.com/gemini/developer-platform/packages/sdk-go" +// +// client := gemini.NewClient( +// gemini.WithEnvironment(gemini.Production), +// gemini.WithAPIKey("your-api-key", "your-api-secret"), +// ) +// +// ticker, err := client.MarketData.GetTicker(ctx, "BTCUSD") +// +// # Fluent Order Placement +// +// amount := gemini.MustDecimal("0.05") +// price := gemini.MustDecimal("64950.00") +// +// // Post-only Maker-or-Cancel limit order with tracking ID +// order, err := client.Trading.PostOnlyBid(ctx, "BTCUSD", amount, price, +// gemini.WithClientOrderID("my-order-1234"), +// ) +// +// # Smart Quote Reconciler (WebSocket-First Market Making) +// +// reconciler := client.NewQuoteReconciler("BTCUSD", +// gemini.WithToleranceBps(0.5), +// gemini.WithQuantization(gemini.MustDecimal("0.01"), gemini.MustDecimal("0.0001")), +// ) +// +// errChan, err := reconciler.StartStreaming(ctx) +// +// result, err := reconciler.Sync(ctx, []gemini.DesiredQuote{ +// {Side: "buy", Price: mid.SubBps(8.0), Amount: size}, +// {Side: "sell", Price: mid.AddBps(8.0), Amount: size}, +// }) +// if err == nil { +// err = result.Err() // Partial cancellation/placement failures +// } +// +// # Real-Time WebSockets & In-Memory Order Book +// +// To enable real-time WebSocket feeds, configure a dialer adapter (e.g. Gorilla WebSocket): +// +// import "github.com/gemini/developer-platform/packages/sdk-go/websocket/gorilla" +// +// client := gemini.NewClient( +// gemini.WithWebSocketDialer(gorilla.NewDialer()), +// ) +// +// Public and private feeds use separate clients and connections: +// +// publicWS := client.PublicWebSocket() +// depth, err := publicWS.SubscribeDepth(ctx, "BTCUSD") +// privateWS := client.PrivateWebSocket() +// orders, err := privateWS.SubscribeOrderEvents(ctx) +// +// Configure an authentication option before using PrivateWebSocket. For API +// keys, use gemini.WithTimeBasedAPIKey so the same key uses epoch-second +// nonces on both REST and private WebSocket requests. +// +// liveBook := orderbook.NewLiveOrderBook("BTCUSD") +// liveBook.OnBBOChanged(func(bbo orderbook.BBO) { +// fmt.Printf("Top of Book: Bid %s | Ask %s\n", bbo.BestBid, bbo.BestAsk) +// }) +// +// # Go 1.23+ Range Iteration (Paginator) +// +// Native iter.Seq2 range-over-function support for paginated endpoints: +// +// for trade, err := range gemini.NewPaginator(ctx, 0, 50, fetcher) { +// if err != nil { +// break +// } +// fmt.Println(trade) +// } +// +// # Error Handling & Classification +// +// Sentinel errors and typed boolean predicates allow clean error handling: +// +// if gemini.IsRateLimit(err) { +// // Handle rate limit +// } +// if gemini.IsInsufficientFunds(err) { +// // Handle balance error +// } +package gemini diff --git a/packages/sdk-go/environment.go b/packages/sdk-go/environment.go new file mode 100644 index 0000000..b3a08d8 --- /dev/null +++ b/packages/sdk-go/environment.go @@ -0,0 +1,38 @@ +package gemini + +// Environment represents a Gemini deployment target. +type Environment string + +const ( + Production Environment = "production" + Sandbox Environment = "sandbox" +) + +// EnvironmentEndpoints holds the URLs for REST, WebSocket, and OAuth endpoints. +type EnvironmentEndpoints struct { + REST string + WebSocket string + OAuthAuthorization string + OAuthToken string +} + +var endpoints = map[Environment]EnvironmentEndpoints{ + Production: { + REST: "https://api.gemini.com", + WebSocket: "wss://ws.gemini.com", + OAuthAuthorization: "https://exchange.gemini.com/auth", + OAuthToken: "https://exchange.gemini.com/auth/token", + }, + Sandbox: { + REST: "https://api.sandbox.gemini.com", + WebSocket: "wss://ws.sandbox.gemini.com", + OAuthAuthorization: "https://exchange.sandbox.gemini.com/auth", + OAuthToken: "https://exchange.sandbox.gemini.com/auth/token", + }, +} + +// EndpointsFor returns the verified endpoints for an environment. +func EndpointsFor(env Environment) (EnvironmentEndpoints, bool) { + endpoints, ok := endpoints[env] + return endpoints, ok +} diff --git a/packages/sdk-go/errors.go b/packages/sdk-go/errors.go new file mode 100644 index 0000000..b436385 --- /dev/null +++ b/packages/sdk-go/errors.go @@ -0,0 +1,289 @@ +package gemini + +import ( + "context" + "errors" + + "github.com/gemini/developer-platform/packages/sdk-go/auth" + "github.com/gemini/developer-platform/packages/sdk-go/transport" + "github.com/gemini/developer-platform/packages/sdk-go/websocket" +) + +// ----------------------------------------------------------------------------- +// Error Types +// ----------------------------------------------------------------------------- + +type ( + // APIError represents a structured error response returned by the Gemini REST API. + APIError = transport.APIError + + // RateLimitError represents an HTTP 429 response with retry delay metadata. + RateLimitError = transport.RateLimitError + + // ResyncRequiredError describes a sequence gap in the live order book update stream. + ResyncRequiredError = transport.ResyncRequiredError +) + +// ----------------------------------------------------------------------------- +// Reason / Error Code Constants (Typed error reason identifiers) +// ----------------------------------------------------------------------------- + +const ( + ReasonInvalidNonce = transport.ReasonInvalidNonce + ReasonGenericNonceError = transport.ReasonGenericNonceError + ReasonMissingNonce = transport.ReasonMissingNonce + ReasonInvalidSignature = transport.ReasonInvalidSignature + ReasonRateLimit = transport.ReasonRateLimit + ReasonUsageLimit = transport.ReasonUsageLimit + ReasonInsufficientFunds = transport.ReasonInsufficientFunds + ReasonMarketClosed = transport.ReasonMarketClosed + ReasonTradingClosed = transport.ReasonTradingClosed + ReasonOrderNotFound = transport.ReasonOrderNotFound + ReasonNoSuchOrder = transport.ReasonNoSuchOrder + ReasonSelfCrossPrevented = transport.ReasonSelfCrossPrevented + ReasonMustAcceptTerms = transport.ReasonMustAcceptTerms +) + +// ----------------------------------------------------------------------------- +// Domain Sentinel Errors (Exchange Business Rules & Trading Invariants) +// ----------------------------------------------------------------------------- + +var ( + // ErrAuthenticationRequired indicates that an authenticated operation was + // attempted without an authentication strategy. + ErrAuthenticationRequired = transport.ErrAuthenticationRequired + + // ErrHTTPSRequired indicates that an authenticated request used an insecure + // URL scheme. + ErrHTTPSRequired = transport.ErrHTTPSRequired + + // ErrInvalidRequestURL indicates that a request URL is missing a host or + // embeds userinfo. + ErrInvalidRequestURL = transport.ErrInvalidRequestURL + + // ErrInvalidSnapshot indicates an invalid WebSocket order-book snapshot + // option. + ErrInvalidSnapshot = websocket.ErrInvalidSnapshot + + // ErrInvalidEnvironment indicates that a client was configured with an + // environment that is not one of the SDK's known deployment targets. + ErrInvalidEnvironment = errors.New("gemini: invalid environment") + + // ErrInvalidEndpointURL indicates that a custom REST or WebSocket endpoint + // is not an absolute URL with the required transport scheme. + ErrInvalidEndpointURL = errors.New("gemini: invalid endpoint URL") + + // ErrInvalidTokenSource indicates that OAuth bearer authentication was + // configured without a usable token source. + ErrInvalidTokenSource = auth.ErrInvalidTokenSource + + // ErrTokenSourceFailure indicates that a configured OAuth token source could + // not provide a token at runtime. + ErrTokenSourceFailure = auth.ErrTokenSourceFailure + + // ErrInvalidHMACCredentials indicates that HMAC authentication was + // configured without a usable API key and secret. + ErrInvalidHMACCredentials = auth.ErrInvalidHMACCredentials + + // ErrInsufficientFunds indicates the account does not have enough available balance. + ErrInsufficientFunds = transport.ErrInsufficientFunds + + // ErrMarketClosed indicates the trading pair is halted or market is closed. + ErrMarketClosed = transport.ErrMarketClosed + + // ErrOrderNotFound indicates the requested order ID or client order ID does not exist. + ErrOrderNotFound = transport.ErrOrderNotFound + + // ErrSelfCrossPrevented indicates the order was rejected to prevent crossing against own resting order. + ErrSelfCrossPrevented = transport.ErrSelfCrossPrevented + + // ErrAcceptTermsRequired indicates prediction market terms of service must be accepted before trading. + ErrAcceptTermsRequired = transport.ErrAcceptTermsRequired + + // ErrInvalidNonce indicates a duplicate or out-of-order HMAC nonce. + ErrInvalidNonce = transport.ErrInvalidNonce + + // ErrMissingNonce indicates the payload did not include the required nonce field. + ErrMissingNonce = transport.ErrMissingNonce + + // ErrInvalidSignature indicates the HMAC signature could not be verified with the secret key. + ErrInvalidSignature = transport.ErrInvalidSignature + + // ErrMissingRole indicates the API key lacks the required permission scope. + ErrMissingRole = transport.ErrMissingRole +) + +// ----------------------------------------------------------------------------- +// API / HTTP Status Sentinel Errors (Transport & Gateway Taxonomy) +// ----------------------------------------------------------------------------- + +var ( + // ErrBadRequest indicates an HTTP 400 Bad Request response. + ErrBadRequest = transport.ErrBadRequest + + // ErrUnauthorized indicates an HTTP 401 Unauthorized response. + ErrUnauthorized = transport.ErrUnauthorized + + // ErrPermissionDenied indicates an HTTP 403 Forbidden response. + ErrPermissionDenied = transport.ErrPermissionDenied + + // ErrNotFound indicates an HTTP 404 Not Found response. + ErrNotFound = transport.ErrNotFound + + // ErrConflict indicates an HTTP 409 Conflict response. + ErrConflict = transport.ErrConflict + + // ErrRateLimited indicates an HTTP 429 Too Many Requests response. + ErrRateLimited = transport.ErrRateLimited + + // ErrInternalServer indicates an HTTP 500 Internal Server Error response. + ErrInternalServer = transport.ErrInternalServer + + // ErrServiceUnavailable indicates an HTTP 502/503/504 Service Unavailable response. + ErrServiceUnavailable = transport.ErrServiceUnavailable + + // RequestIDFromError extracts the Gemini Request ID from an error if present. + RequestIDFromError = transport.RequestIDFromError +) + +// ----------------------------------------------------------------------------- +// Client & Stream Sentinel Errors (SDK State & Local Stream Failures) +// ----------------------------------------------------------------------------- + +var ( + // ErrConnectionClosed indicates the underlying network connection was closed. + ErrConnectionClosed = transport.ErrConnectionClosed + + // ErrDeadlineExceeded indicates the request exceeded the client-specified context deadline. + ErrDeadlineExceeded = transport.ErrDeadlineExceeded + + // ErrResyncRequired indicates an order book sequence gap occurred and a full snapshot resync is required. + ErrResyncRequired = transport.ErrResyncRequired +) + +// ----------------------------------------------------------------------------- +// Helper Predicates (Distinguishing API vs Domain vs Client Errors) +// ----------------------------------------------------------------------------- + +// AsAPIError attempts to extract an *APIError from err. +func AsAPIError(err error) (*APIError, bool) { + if err == nil { + return nil, false + } + var apiErr *APIError + if errors.As(err, &apiErr) { + return apiErr, true + } + var rateLimitErr *RateLimitError + if errors.As(err, &rateLimitErr) { + return &rateLimitErr.APIError, true + } + return nil, false +} + +// IsAPIError reports whether err was returned by the Gemini REST API. +func IsAPIError(err error) bool { + _, ok := AsAPIError(err) + return ok +} + +// IsDomainError reports whether err is an exchange business logic/domain error. +func IsDomainError(err error) bool { + if apiErr, ok := AsAPIError(err); ok && apiErr.IsDomain() { + return true + } + return errors.Is(err, ErrInsufficientFunds) || + errors.Is(err, ErrMarketClosed) || + errors.Is(err, ErrOrderNotFound) || + errors.Is(err, ErrSelfCrossPrevented) || + errors.Is(err, ErrAcceptTermsRequired) || + errors.Is(err, ErrInvalidNonce) || + errors.Is(err, ErrMissingNonce) || + errors.Is(err, ErrInvalidSignature) || + errors.Is(err, ErrMissingRole) +} + +// IsRateLimit reports whether err indicates a 429 Rate Limit response. +func IsRateLimit(err error) bool { + return errors.Is(err, ErrRateLimited) +} + +// IsInsufficientFunds reports whether err indicates insufficient balance for an order. +func IsInsufficientFunds(err error) bool { + return errors.Is(err, ErrInsufficientFunds) +} + +// IsMarketClosed reports whether err indicates the market or trading pair is closed. +func IsMarketClosed(err error) bool { + return errors.Is(err, ErrMarketClosed) +} + +// IsOrderNotFound reports whether err indicates the order was not found. +func IsOrderNotFound(err error) bool { + return errors.Is(err, ErrOrderNotFound) +} + +// IsSelfCrossPrevented reports whether err indicates self-trade prevention triggered. +func IsSelfCrossPrevented(err error) bool { + return errors.Is(err, ErrSelfCrossPrevented) +} + +// IsTermsRequired reports whether err indicates prediction market terms must be accepted. +func IsTermsRequired(err error) bool { + return errors.Is(err, ErrAcceptTermsRequired) +} + +// IsAuthError reports whether err was caused by invalid signature, missing nonce, or bad API keys. +func IsAuthError(err error) bool { + return errors.Is(err, ErrInvalidSignature) || + errors.Is(err, ErrInvalidNonce) || + errors.Is(err, ErrMissingNonce) || + errors.Is(err, ErrMissingRole) || + errors.Is(err, ErrUnauthorized) +} + +// IsNotFound reports whether err indicates an entity or order was not found (404 or OrderNotFound). +func IsNotFound(err error) bool { + return errors.Is(err, ErrOrderNotFound) || errors.Is(err, ErrNotFound) +} + +// IsBadRequest reports whether err indicates a 400 Bad Request error. +func IsBadRequest(err error) bool { + if errors.Is(err, ErrBadRequest) { + return true + } + if apiErr, ok := AsAPIError(err); ok && apiErr.StatusCode == 400 { + return true + } + return false +} + +// IsPermissionDenied reports whether err indicates a 403 Forbidden error or missing API key role. +func IsPermissionDenied(err error) bool { + return errors.Is(err, ErrPermissionDenied) || errors.Is(err, ErrMissingRole) +} + +// IsConflict reports whether err indicates a 409 Conflict error. +func IsConflict(err error) bool { + return errors.Is(err, ErrConflict) +} + +// IsInternalServerError reports whether err indicates a 500 Internal Server error. +func IsInternalServerError(err error) bool { + return errors.Is(err, ErrInternalServer) +} + +// IsServiceUnavailable reports whether err indicates 502/503/504 exchange maintenance or outage. +func IsServiceUnavailable(err error) bool { + return errors.Is(err, ErrServiceUnavailable) +} + +// IsResyncRequired reports whether err indicates an order book sequence gap requiring snapshot resync. +func IsResyncRequired(err error) bool { + return errors.Is(err, ErrResyncRequired) +} + +// IsTimeout reports whether err indicates a network or context deadline timeout. +func IsTimeout(err error) bool { + return errors.Is(err, ErrDeadlineExceeded) || errors.Is(err, context.DeadlineExceeded) +} diff --git a/packages/sdk-go/errors_test.go b/packages/sdk-go/errors_test.go new file mode 100644 index 0000000..745b864 --- /dev/null +++ b/packages/sdk-go/errors_test.go @@ -0,0 +1,173 @@ +package gemini_test + +import ( + "errors" + "net/http" + "testing" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go" + "github.com/gemini/developer-platform/packages/sdk-go/transport" +) + +func TestErrors_DomainVsAPIClassification(t *testing.T) { + // 1. Domain Errors originating from API responses with specific reasons + domainReasons := []struct { + reason string + expected error + checkFn func(error) bool + }{ + {"InsufficientFunds", gemini.ErrInsufficientFunds, gemini.IsInsufficientFunds}, + {"MarketClosed", gemini.ErrMarketClosed, gemini.IsMarketClosed}, + {"TradingClosed", gemini.ErrMarketClosed, gemini.IsMarketClosed}, + {"OrderNotFound", gemini.ErrOrderNotFound, gemini.IsOrderNotFound}, + {"NoSuchOrder", gemini.ErrOrderNotFound, gemini.IsOrderNotFound}, + {"SelfCrossPrevented", gemini.ErrSelfCrossPrevented, gemini.IsSelfCrossPrevented}, + {"MustAcceptTerms", gemini.ErrAcceptTermsRequired, gemini.IsTermsRequired}, + {"MissingRole", gemini.ErrMissingRole, gemini.IsPermissionDenied}, + {"InvalidNonce", gemini.ErrInvalidNonce, gemini.IsAuthError}, + {"MissingNonce", gemini.ErrInvalidNonce, gemini.IsAuthError}, + {"InvalidSignature", gemini.ErrInvalidSignature, gemini.IsAuthError}, + } + + for _, tt := range domainReasons { + t.Run("Reason_"+tt.reason, func(t *testing.T) { + apiErr := &gemini.APIError{ + StatusCode: http.StatusBadRequest, + Result: "error", + Reason: tt.reason, + Message: "Domain error occurred: " + tt.reason, + RequestID: "req-12345", + } + + // Must be classified as both an APIError and a DomainError + if !gemini.IsAPIError(apiErr) { + t.Fatalf("expected IsAPIError to be true for reason %s", tt.reason) + } + if !gemini.IsDomainError(apiErr) { + t.Fatalf("expected IsDomainError to be true for reason %s", tt.reason) + } + if !apiErr.IsDomain() { + t.Fatalf("expected APIError.IsDomain to be true for reason %s", tt.reason) + } + if !errors.Is(apiErr, tt.expected) { + t.Fatalf("expected errors.Is(apiErr, %v) to be true for reason %s", tt.expected, tt.reason) + } + if !tt.checkFn(apiErr) { + t.Fatalf("expected predicate check to return true for reason %s", tt.reason) + } + if reqID := gemini.RequestIDFromError(apiErr); reqID != "req-12345" { + t.Fatalf("expected request ID 'req-12345', got '%s'", reqID) + } + }) + } + + // 2. Pure API / HTTP Status Errors without domain reasons + httpStatuses := []struct { + status int + expected error + checkFn func(error) bool + }{ + {http.StatusBadRequest, gemini.ErrBadRequest, gemini.IsBadRequest}, + {http.StatusUnauthorized, gemini.ErrUnauthorized, gemini.IsAuthError}, + {http.StatusForbidden, gemini.ErrPermissionDenied, gemini.IsPermissionDenied}, + {http.StatusNotFound, gemini.ErrNotFound, gemini.IsNotFound}, + {http.StatusConflict, gemini.ErrConflict, gemini.IsConflict}, + {http.StatusInternalServerError, gemini.ErrInternalServer, gemini.IsInternalServerError}, + {http.StatusServiceUnavailable, gemini.ErrServiceUnavailable, gemini.IsServiceUnavailable}, + {http.StatusBadGateway, gemini.ErrServiceUnavailable, gemini.IsServiceUnavailable}, + {http.StatusGatewayTimeout, gemini.ErrServiceUnavailable, gemini.IsServiceUnavailable}, + } + + for _, tt := range httpStatuses { + t.Run("Status_"+http.StatusText(tt.status), func(t *testing.T) { + apiErr := &gemini.APIError{ + StatusCode: tt.status, + RequestID: "req-status", + } + + if !gemini.IsAPIError(apiErr) { + t.Fatalf("expected IsAPIError to be true for status %d", tt.status) + } + if gemini.IsDomainError(apiErr) { + t.Fatalf("expected IsDomainError to be false for generic HTTP status %d", tt.status) + } + if !errors.Is(apiErr, tt.expected) { + t.Fatalf("expected errors.Is(apiErr, %v) to be true for status %d", tt.expected, tt.status) + } + if !tt.checkFn(apiErr) { + t.Fatalf("expected predicate check to return true for status %d", tt.status) + } + }) + } + + // 3. RateLimitError with retry metadata + rateLimitErr := &gemini.RateLimitError{ + APIError: gemini.APIError{ + StatusCode: http.StatusTooManyRequests, + RequestID: "req-429", + }, + RetryAfter: 2 * time.Second, + } + + if !gemini.IsAPIError(rateLimitErr) { + t.Fatal("expected IsAPIError to be true for RateLimitError") + } + if !gemini.IsRateLimit(rateLimitErr) { + t.Fatal("expected IsRateLimit to be true for RateLimitError") + } + if !errors.Is(rateLimitErr, gemini.ErrRateLimited) { + t.Fatal("expected errors.Is(rateLimitErr, ErrRateLimited) to be true") + } + if reqID := gemini.RequestIDFromError(rateLimitErr); reqID != "req-429" { + t.Fatalf("expected request ID 'req-429', got '%s'", reqID) + } + + // 4. Client / Local Errors (Not API errors) + clientErrors := []struct { + err error + checkFn func(error) bool + }{ + {gemini.ErrResyncRequired, gemini.IsResyncRequired}, + {gemini.ErrDeadlineExceeded, gemini.IsTimeout}, + {&transport.ResyncRequiredError{LastUpdateID: 100, FirstUpdateID: 105}, gemini.IsResyncRequired}, + } + + for _, tt := range clientErrors { + if gemini.IsAPIError(tt.err) { + t.Fatalf("expected IsAPIError to be false for local error: %v", tt.err) + } + if !tt.checkFn(tt.err) { + t.Fatalf("expected predicate to be true for local error: %v", tt.err) + } + } +} + +func TestErrors_ErrorsAsAndReasonConstants(t *testing.T) { + rawErr := &gemini.APIError{ + StatusCode: http.StatusBadRequest, + Result: "error", + Reason: gemini.ReasonInsufficientFunds, + Message: "Failed to place order: insufficient balance", + RequestID: "req-order-123", + } + + var geminiErr *gemini.APIError + if !errors.As(rawErr, &geminiErr) { + t.Fatalf("expected errors.As(err, &geminiErr) to succeed") + } + + switch geminiErr.Reason { + case gemini.ReasonInsufficientFunds: + // expected + default: + t.Fatalf("unexpected reason: %s", geminiErr.Reason) + } + + if geminiErr.StatusCode != 400 { + t.Fatalf("expected status code 400, got %d", geminiErr.StatusCode) + } + if geminiErr.RequestID != "req-order-123" { + t.Fatalf("expected request ID 'req-order-123', got '%s'", geminiErr.RequestID) + } +} diff --git a/packages/sdk-go/example_test.go b/packages/sdk-go/example_test.go new file mode 100644 index 0000000..704e1e7 --- /dev/null +++ b/packages/sdk-go/example_test.go @@ -0,0 +1,292 @@ +package gemini_test + +import ( + "context" + "encoding/json" + "fmt" + "log" + "net/http" + "net/http/httptest" + "sync/atomic" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go" + "github.com/gemini/developer-platform/packages/sdk-go/generated/trading" + "github.com/gemini/developer-platform/packages/sdk-go/transport" + "github.com/gemini/developer-platform/packages/sdk-go/websocket" + "github.com/gemini/developer-platform/packages/sdk-go/websocket/orderbook" +) + +func newExampleRESTClient(server *httptest.Server, authenticated bool) *gemini.Client { + opts := []gemini.Option{ + gemini.WithCustomRESTURL(server.URL), + gemini.WithHTTPClient(server.Client()), + gemini.WithRetryPolicy(transport.RetryPolicy{MaxRetries: 0}), + } + if authenticated { + opts = append(opts, gemini.WithAPIKey("example-key", "example-secret")) + } + return gemini.NewClient(opts...) +} + +// Example_basic demonstrates initializing the Gemini client and fetching public ticker data. +func Example_basic() { + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/v1/symbols" { + http.NotFound(w, r) + return + } + _ = json.NewEncoder(w).Encode([]string{"BTCUSD", "ETHUSD"}) + })) + defer server.Close() + client := newExampleRESTClient(server, false) + defer client.Close() + + ctx := context.Background() + symbols, err := client.MarketData.GetSymbols(ctx) + if err != nil { + log.Fatalf("failed fetching symbols: %v", err) + } + + fmt.Printf("Supported symbol count: %d\n", len(symbols)) + + // Output: + // Supported symbol count: 2 +} + +// Example_trading demonstrates authenticating with API keys and placing a limit buy order. +func Example_trading() { + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/v1/order/new" { + http.NotFound(w, r) + return + } + _ = json.NewEncoder(w).Encode(map[string]any{"order_id": "order-123", "is_live": true}) + })) + defer server.Close() + client := newExampleRESTClient(server, true) + defer client.Close() + + ctx := context.Background() + + order, err := client.Trading.NewOrder(ctx, &trading.NewOrderRequest{ + Symbol: "BTCUSD", + Amount: "0.10", + Price: "65000.00", + Side: trading.NewOrderRequestSideBuy, + Type: trading.NewOrderRequestTypeExchangeLimit, + }) + if err != nil { + log.Fatalf("failed placing order: %v", err) + } + + fmt.Printf("Order placed: %s\n", *order.OrderId) + + // Output: + // Order placed: order-123 +} + +// Example_liveOrderBook demonstrates synchronizing an in-memory L2 order book. +func Example_liveOrderBook() { + liveBook := orderbook.NewLiveOrderBook("BTCUSD") + + // Apply initial snapshot + liveBook.ApplySnapshot(&websocket.OrderBookSnapshot{ + LastUpdateID: 100, + Bids: [][]string{{"65000.00", "1.5"}}, + Asks: [][]string{{"65001.00", "2.0"}}, + }) + + // Best bid & ask are available with sub-microsecond latency + if bestBid, ok := liveBook.Book().BestBid(); ok { + fmt.Printf("Best Bid: %s @ %s\n", bestBid.Price, bestBid.Amount) + } + + // Output: + // Best Bid: 65000.00 @ 1.5 +} + +// Example_managedHeartbeat demonstrates starting an autonomous session heartbeat worker. +func Example_managedHeartbeat() { + received := make(chan struct{}, 1) + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/v1/heartbeat" { + http.NotFound(w, r) + return + } + received <- struct{}{} + _ = json.NewEncoder(w).Encode(map[string]string{"result": "ok"}) + })) + defer server.Close() + client := newExampleRESTClient(server, true) + defer client.Close() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Keep trading session alive every 5 seconds + session := client.Heartbeat.Start(ctx, 5*time.Second) + defer session.Stop() + select { + case <-received: + fmt.Println("Heartbeat sent") + case <-time.After(time.Second): + log.Fatal("heartbeat was not sent") + } + + // Monitor errors in background + go func() { + for err := range session.Errors() { + log.Printf("Heartbeat delivery issue: %v", err) + } + }() + + // Output: + // Heartbeat sent +} + +// CustomMetricsHook satisfies transport.Hook for telemetry integrations. +type CustomMetricsHook struct{} + +var _ transport.Hook = (*CustomMetricsHook)(nil) + +func (h *CustomMetricsHook) OnRequestStart(ctx context.Context, req *http.Request) context.Context { + return ctx +} + +func (h *CustomMetricsHook) OnRequestEnd(ctx context.Context, req *http.Request, resp *http.Response, duration time.Duration, err error) { + // Emit Prometheus / OpenTelemetry histogram latency metrics +} + +func (h *CustomMetricsHook) OnRetry(ctx context.Context, req *http.Request, attempt int, backoff time.Duration, err error) { + // Increment retry counter +} + +func (h *CustomMetricsHook) OnRateLimit(ctx context.Context, req *http.Request, retryAfter time.Duration) { + // Increment rate limit counter +} + +// Example_observabilityHooks demonstrates attaching zero-dependency telemetry hooks. +func Example_observabilityHooks() { + client := gemini.NewClient( + gemini.WithHooks(&CustomMetricsHook{}), + ) + defer client.Close() + + fmt.Println("Observability hooks configured") + + // Output: + // Observability hooks configured +} + +// Example_fluentTrading demonstrates one-line maker post-only and IOC order placement. +func Example_fluentTrading() { + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/v1/order/new" { + http.NotFound(w, r) + return + } + _ = json.NewEncoder(w).Encode(map[string]any{"order_id": "maker-bid-1001", "is_live": true}) + })) + defer server.Close() + client := newExampleRESTClient(server, true) + defer client.Close() + + ctx := context.Background() + amount := gemini.MustDecimal("0.05") + bidPrice := gemini.MustDecimal("64950.00") + + // Post-only maker order with client tracking ID + order, err := client.Trading.PostOnlyBid(ctx, "BTCUSD", amount, bidPrice, + gemini.WithClientOrderID("maker-bid-1001"), + ) + if err != nil { + log.Fatalf("failed placing maker quote: %v", err) + } + + fmt.Printf("Maker bid placed: %s\n", *order.OrderId) + + // Output: + // Maker bid placed: maker-bid-1001 +} + +// Example_quoteReconciler demonstrates declarative market making ladder synchronization. +func Example_quoteReconciler() { + var nextOrderID atomic.Int64 + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/v1/orders": + _ = json.NewEncoder(w).Encode([]any{}) + case "/v1/order/new": + id := nextOrderID.Add(1) + _ = json.NewEncoder(w).Encode(map[string]any{ + "order_id": fmt.Sprintf("quote-%d", id), + "is_live": true, + }) + default: + http.NotFound(w, r) + } + })) + defer server.Close() + client := newExampleRESTClient(server, true) + defer client.Close() + + ctx := context.Background() + + // Initialize reconciler with 0.5 bps tolerance band and exchange tick size + reconciler := client.NewQuoteReconciler("BTCUSD", + gemini.WithToleranceBps(0.5), + gemini.WithQuantization(gemini.MustDecimal("0.01"), gemini.MustDecimal("0.0001")), + ) + if err := reconciler.Hydrate(ctx); err != nil { + log.Fatalf("failed hydrating active quotes: %v", err) + } + + // Target 2-sided quoting ladder + mid := gemini.MustDecimal("65000.00") + size := gemini.MustDecimal("0.05") + + targetLadder := []gemini.DesiredQuote{ + {Side: "buy", Price: mid.SubBps(10.0), Amount: size}, + {Side: "sell", Price: mid.AddBps(10.0), Amount: size}, + } + + result, err := reconciler.Sync(ctx, targetLadder) + if err != nil { + log.Fatalf("reconciliation failed: %v", err) + } + if err := result.Err(); err != nil { + log.Fatalf("reconciliation completed with partial failures: %v", err) + } + + fmt.Printf("Quotes synced: Kept=%d, Cancelled=%d, Placed=%d\n", + result.Kept, result.Cancelled, result.Placed) + + // Output: + // Quotes synced: Kept=0, Cancelled=0, Placed=2 +} + +// Example_pagination demonstrates native Go 1.23+ iter.Seq2 range-over-function pagination. +func Example_pagination() { + ctx := context.Background() + + // Create an iterator fetching pages of trade records + tradesIter := gemini.NewPaginator(ctx, 0, 50, func(ctx context.Context, offset, limit int) ([]string, bool, error) { + // Fetch items at offset + items := []string{"trade-1", "trade-2"} + hasMore := false + return items, hasMore, nil + }) + + // Iterate with native Go 1.23 for-range loop + for item, err := range tradesIter { + if err != nil { + log.Fatalf("pagination error: %v", err) + } + fmt.Printf("Processing item: %s\n", item) + } + + // Output: + // Processing item: trade-1 + // Processing item: trade-2 +} diff --git a/packages/sdk-go/geminitest/mock_server.go b/packages/sdk-go/geminitest/mock_server.go new file mode 100644 index 0000000..f0de208 --- /dev/null +++ b/packages/sdk-go/geminitest/mock_server.go @@ -0,0 +1,338 @@ +package geminitest + +import ( + "crypto/hmac" + "crypto/sha512" + "encoding/base64" + "encoding/hex" + "encoding/json" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "sync" +) + +// MockServer provides an in-process Gemini REST test server verifying HMAC signatures and headers. +type MockServer struct { + server *httptest.Server + mu sync.Mutex + lastNonce int64 + apiKey string + apiSecret string + bearerToken string + termsAccepted bool +} + +// NewMockServer creates and starts a new mock Gemini test server validating HMAC credentials. +func NewMockServer(apiKey, apiSecret string) *MockServer { + return newMockServerInternal(apiKey, apiSecret, "") +} + +// NewMockOAuthServer creates and starts a new mock Gemini test server validating OAuth Bearer tokens. +func NewMockOAuthServer(bearerToken string) *MockServer { + return newMockServerInternal("", "", bearerToken) +} + +func newMockServerInternal(apiKey, apiSecret, bearerToken string) *MockServer { + ms := &MockServer{ + apiKey: apiKey, + apiSecret: apiSecret, + bearerToken: bearerToken, + } + + mux := http.NewServeMux() + + // Public Market Data + mux.HandleFunc("/v1/symbols", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + if r.Header.Get("X-GEMINI-APIKEY") != "" || r.Header.Get("Authorization") != "" { + w.WriteHeader(http.StatusBadRequest) + return + } + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode([]string{"btcusd", "ethusd", "solusd"}) + }) + + mux.HandleFunc("/v1/pubticker/btcusd", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{ + "bid": "65000.00", + "ask": "65001.00", + "last": "65000.50", + "volume": map[string]any{"BTC": "1200.5", "USD": "78000000"}, + }) + }) + + mux.HandleFunc("/v1/book/btcusd", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{ + "bids": []map[string]string{{"price": "65000.00", "amount": "1.0", "timestamp": "1700000000"}}, + "asks": []map[string]string{{"price": "65001.00", "amount": "1.5", "timestamp": "1700000000"}}, + }) + }) + + // Private Authenticated Endpoints + mux.HandleFunc("/v1/order/new", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + payload, err := ms.validateAuth(r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "InvalidSignature", "message": err.Error()}) + return + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{ + "order_id": "987654321", + "id": "987654321", + "symbol": payload["symbol"], + "side": payload["side"], + "type": payload["type"], + "price": payload["price"], + "original_amount": payload["amount"], + "executed_amount": "0", + "remaining_amount": payload["amount"], + "is_live": true, + "is_cancelled": false, + "is_hidden": false, + "avg_execution_price": "0.00", + }) + }) + + mux.HandleFunc("/v1/order/cancel", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + payload, err := ms.validateAuth(r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "InvalidSignature", "message": err.Error()}) + return + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{ + "order_id": payload["order_id"], + "is_cancelled": true, + "is_live": false, + }) + }) + + mux.HandleFunc("/v1/balances", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + _, err := ms.validateAuth(r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "InvalidSignature", "message": err.Error()}) + return + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode([]map[string]any{ + {"currency": "USD", "amount": 100000.00, "available": 95000.00, "type": "exchange"}, + {"currency": "BTC", "amount": 10.5, "available": 8.0, "type": "exchange"}, + }) + }) + + mux.HandleFunc("/v1/oauth/revokeByToken", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + if _, err := ms.validateAuth(r); err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "Unauthorized", "message": err.Error()}) + return + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{"message": "token revoked"}) + }) + + // Prediction Markets Terms Endpoints + mux.HandleFunc("/v1/prediction-markets/terms/accept", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + _, err := ms.validateAuth(r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "InvalidSignature", "message": err.Error()}) + return + } + w.Header().Set("Content-Type", "application/json") + ms.mu.Lock() + ms.termsAccepted = true + ms.mu.Unlock() + _ = json.NewEncoder(w).Encode(map[string]any{"success": true}) + }) + + mux.HandleFunc("/v1/prediction-markets/order", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + _, err := ms.validateAuth(r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "InvalidSignature", "message": err.Error()}) + return + } + ms.mu.Lock() + termsAccepted := ms.termsAccepted + ms.mu.Unlock() + if !termsAccepted { + w.WriteHeader(http.StatusBadRequest) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "MustAcceptTerms", "message": "terms must be accepted"}) + return + } + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{"orderId": 12345, "status": "open"}) + }) + + // Staking Balances + mux.HandleFunc("/v1/balances/staking", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + _, err := ms.validateAuth(r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "InvalidSignature", "message": err.Error()}) + return + } + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode([]map[string]any{ + {"currency": "ETH", "amount": 10.0, "amountAvailable": 8.0}, + }) + }) + + // Transfers V2 + mux.HandleFunc("/v2/transfers", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + _, err := ms.validateAuth(r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + _ = json.NewEncoder(w).Encode(map[string]any{"result": "error", "reason": "InvalidSignature", "message": err.Error()}) + return + } + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode([]map[string]any{ + {"type": "Deposit", "currency": "ETH", "amount": "10.0", "status": "Complete"}, + }) + }) + + // Use TLS so the high-level SDK client exercises the same transport + // security requirement as production endpoints. + ms.server = httptest.NewTLSServer(mux) + return ms +} + +func (ms *MockServer) URL() string { + return ms.server.URL +} + +// HTTPClient returns an HTTP client configured to trust this test server's +// ephemeral certificate. It must be passed to the high-level SDK client when +// using URL so tests do not disable TLS verification globally. +func (ms *MockServer) HTTPClient() *http.Client { + return ms.server.Client() +} + +func (ms *MockServer) Close() { + ms.server.Close() +} + +func (ms *MockServer) validateAuth(r *http.Request) (map[string]any, error) { + // 1. Check OAuth 2.0 Bearer Authorization header + authHeader := r.Header.Get("Authorization") + if strings.HasPrefix(authHeader, "Bearer ") { + token := strings.TrimPrefix(authHeader, "Bearer ") + if ms.bearerToken == "" || token != ms.bearerToken { + return nil, http.ErrNotSupported + } + + payloadB64 := r.Header.Get("X-GEMINI-PAYLOAD") + if payloadB64 == "" { + return nil, http.ErrNotSupported + } + rawJSON, err := base64.StdEncoding.DecodeString(payloadB64) + if err != nil { + return nil, err + } + var payload map[string]any + if err := json.Unmarshal(rawJSON, &payload); err != nil { + return nil, err + } + if payload["request"] != r.URL.Path { + return nil, http.ErrNotSupported + } + if _, hasNonce := payload["nonce"]; hasNonce { + return nil, http.ErrNotSupported + } + return payload, nil + } + + // 2. Check HMAC-SHA384 API Key + Signature + apiKey := r.Header.Get("X-GEMINI-APIKEY") + payloadB64 := r.Header.Get("X-GEMINI-PAYLOAD") + sig := r.Header.Get("X-GEMINI-SIGNATURE") + + if apiKey != ms.apiKey || ms.apiKey == "" { + return nil, http.ErrNotSupported + } + + mac := hmac.New(sha512.New384, []byte(ms.apiSecret)) + mac.Write([]byte(payloadB64)) + expectedSig := hex.EncodeToString(mac.Sum(nil)) + + if sig != expectedSig { + return nil, http.ErrNotSupported + } + + rawJSON, err := base64.StdEncoding.DecodeString(payloadB64) + if err != nil { + return nil, err + } + + var payload map[string]any + if err := json.Unmarshal(rawJSON, &payload); err != nil { + return nil, err + } + + nonceStr, _ := payload["nonce"].(string) + nonceVal, _ := strconv.ParseInt(nonceStr, 10, 64) + + ms.mu.Lock() + defer ms.mu.Unlock() + if nonceVal <= ms.lastNonce { + return nil, http.ErrNotSupported + } + ms.lastNonce = nonceVal + + return payload, nil +} diff --git a/packages/sdk-go/generated/account/types.gen.go b/packages/sdk-go/generated/account/types.gen.go new file mode 100644 index 0000000..f4ced9a --- /dev/null +++ b/packages/sdk-go/generated/account/types.gen.go @@ -0,0 +1,3674 @@ +// Code generated from rest.yaml (Account Administration, Fund Management, OAuth, Staking). DO NOT EDIT. + +// Package account provides primitives to interact with the openapi HTTP API. +// +// Code generated by oapi-codegen. DO NOT EDIT. +package account + +import ( + "encoding/json" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/internal/runtime" + openapi_types "github.com/gemini/developer-platform/packages/sdk-go/types" +) + +const ( + ApiKeyAuthScopes apiKeyAuthContextKey = "apiKeyAuth.Scopes" + PayloadAuthScopes payloadAuthContextKey = "payloadAuth.Scopes" + SignatureAuthScopes signatureAuthContextKey = "signatureAuth.Scopes" +) + +// Defines values for BalanceType. +const ( + Exchange BalanceType = "exchange" +) + +// Valid indicates whether the value is a known member of the BalanceType enum. +func (e BalanceType) Valid() bool { + switch e { + case Exchange: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseReason. +const ( + ExceedsPriceLimits CancelOrderResponseReason = "ExceedsPriceLimits" + FillOrKillWouldNotFill CancelOrderResponseReason = "FillOrKillWouldNotFill" + ImmediateOrCancelWouldPost CancelOrderResponseReason = "ImmediateOrCancelWouldPost" + MakerOrCancelWouldTake CancelOrderResponseReason = "MakerOrCancelWouldTake" + MarketClosed CancelOrderResponseReason = "MarketClosed" + Requested CancelOrderResponseReason = "Requested" + SelfCrossPrevented CancelOrderResponseReason = "SelfCrossPrevented" + TradingClosed CancelOrderResponseReason = "TradingClosed" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseReason enum. +func (e CancelOrderResponseReason) Valid() bool { + switch e { + case ExceedsPriceLimits: + return true + case FillOrKillWouldNotFill: + return true + case ImmediateOrCancelWouldPost: + return true + case MakerOrCancelWouldTake: + return true + case MarketClosed: + return true + case Requested: + return true + case SelfCrossPrevented: + return true + case TradingClosed: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseSide. +const ( + CancelOrderResponseSideBuy CancelOrderResponseSide = "buy" + CancelOrderResponseSideSell CancelOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseSide enum. +func (e CancelOrderResponseSide) Valid() bool { + switch e { + case CancelOrderResponseSideBuy: + return true + case CancelOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseType. +const ( + CancelOrderResponseTypeExchangeLimit CancelOrderResponseType = "exchange limit" + CancelOrderResponseTypeExchangeMarket CancelOrderResponseType = "exchange market" + CancelOrderResponseTypeExchangeStopLimit CancelOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseType enum. +func (e CancelOrderResponseType) Valid() bool { + switch e { + case CancelOrderResponseTypeExchangeLimit: + return true + case CancelOrderResponseTypeExchangeMarket: + return true + case CancelOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for ClearingOrderSide. +const ( + ClearingOrderSideBuy ClearingOrderSide = "buy" + ClearingOrderSideSell ClearingOrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the ClearingOrderSide enum. +func (e ClearingOrderSide) Valid() bool { + switch e { + case ClearingOrderSideBuy: + return true + case ClearingOrderSideSell: + return true + default: + return false + } +} + +// Defines values for FundingPaymentEventType. +const ( + FundingPaymentEventTypeHourlyFundingTransfer FundingPaymentEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentEventType enum. +func (e FundingPaymentEventType) Valid() bool { + switch e { + case FundingPaymentEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemAction. +const ( + FundingPaymentReportItemActionCredit FundingPaymentReportItemAction = "Credit" + FundingPaymentReportItemActionDebit FundingPaymentReportItemAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemAction enum. +func (e FundingPaymentReportItemAction) Valid() bool { + switch e { + case FundingPaymentReportItemActionCredit: + return true + case FundingPaymentReportItemActionDebit: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemEventType. +const ( + FundingPaymentReportItemEventTypeHourlyFundingTransfer FundingPaymentReportItemEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemEventType enum. +func (e FundingPaymentReportItemEventType) Valid() bool { + switch e { + case FundingPaymentReportItemEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingTransferAction. +const ( + FundingTransferActionCredit FundingTransferAction = "Credit" + FundingTransferActionDebit FundingTransferAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingTransferAction enum. +func (e FundingTransferAction) Valid() bool { + switch e { + case FundingTransferActionCredit: + return true + case FundingTransferActionDebit: + return true + default: + return false + } +} + +// Defines values for InstantQuoteSide. +const ( + InstantQuoteSideBuy InstantQuoteSide = "buy" + InstantQuoteSideSell InstantQuoteSide = "sell" +) + +// Valid indicates whether the value is a known member of the InstantQuoteSide enum. +func (e InstantQuoteSide) Valid() bool { + switch e { + case InstantQuoteSideBuy: + return true + case InstantQuoteSideSell: + return true + default: + return false + } +} + +// Defines values for InterestRateInfoInterval. +const ( + Hour InterestRateInfoInterval = "hour" +) + +// Valid indicates whether the value is a known member of the InterestRateInfoInterval enum. +func (e InterestRateInfoInterval) Valid() bool { + switch e { + case Hour: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseSide. +const ( + LimitOrderResponseSideBuy LimitOrderResponseSide = "buy" + LimitOrderResponseSideSell LimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseSide enum. +func (e LimitOrderResponseSide) Valid() bool { + switch e { + case LimitOrderResponseSideBuy: + return true + case LimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseType. +const ( + LimitOrderResponseTypeExchangeLimit LimitOrderResponseType = "exchange limit" + LimitOrderResponseTypeExchangeMarket LimitOrderResponseType = "exchange market" + LimitOrderResponseTypeExchangeStopLimit LimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseType enum. +func (e LimitOrderResponseType) Valid() bool { + switch e { + case LimitOrderResponseTypeExchangeLimit: + return true + case LimitOrderResponseTypeExchangeMarket: + return true + case LimitOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for MyTradeBreak. +const ( + Empty MyTradeBreak = "" + TradeCorrect MyTradeBreak = "trade correct" +) + +// Valid indicates whether the value is a known member of the MyTradeBreak enum. +func (e MyTradeBreak) Valid() bool { + switch e { + case Empty: + return true + case TradeCorrect: + return true + default: + return false + } +} + +// Defines values for MyTradeType. +const ( + MyTradeTypeBuy MyTradeType = "Buy" + MyTradeTypeSell MyTradeType = "Sell" +) + +// Valid indicates whether the value is a known member of the MyTradeType enum. +func (e MyTradeType) Valid() bool { + switch e { + case MyTradeTypeBuy: + return true + case MyTradeTypeSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestOptions. +const ( + FillOrKill NewOrderRequestOptions = "fill-or-kill" + ImmediateOrCancel NewOrderRequestOptions = "immediate-or-cancel" + MakerOrCancel NewOrderRequestOptions = "maker-or-cancel" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestOptions enum. +func (e NewOrderRequestOptions) Valid() bool { + switch e { + case FillOrKill: + return true + case ImmediateOrCancel: + return true + case MakerOrCancel: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestSide. +const ( + NewOrderRequestSideBuy NewOrderRequestSide = "buy" + NewOrderRequestSideSell NewOrderRequestSide = "sell" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestSide enum. +func (e NewOrderRequestSide) Valid() bool { + switch e { + case NewOrderRequestSideBuy: + return true + case NewOrderRequestSideSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestType. +const ( + NewOrderRequestTypeExchangeLimit NewOrderRequestType = "exchange limit" + NewOrderRequestTypeExchangeMarket NewOrderRequestType = "exchange market" + NewOrderRequestTypeExchangeStopLimit NewOrderRequestType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestType enum. +func (e NewOrderRequestType) Valid() bool { + switch e { + case NewOrderRequestTypeExchangeLimit: + return true + case NewOrderRequestTypeExchangeMarket: + return true + case NewOrderRequestTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for OrderSide. +const ( + OrderSideBuy OrderSide = "buy" + OrderSideSell OrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the OrderSide enum. +func (e OrderSide) Valid() bool { + switch e { + case OrderSideBuy: + return true + case OrderSideSell: + return true + default: + return false + } +} + +// Defines values for OrderTradesType. +const ( + OrderTradesTypeBuy OrderTradesType = "Buy" + OrderTradesTypeSell OrderTradesType = "Sell" +) + +// Valid indicates whether the value is a known member of the OrderTradesType enum. +func (e OrderTradesType) Valid() bool { + switch e { + case OrderTradesTypeBuy: + return true + case OrderTradesTypeSell: + return true + default: + return false + } +} + +// Defines values for OrderType. +const ( + OrderTypeExchangeLimit OrderType = "exchange limit" + OrderTypeExchangeMarket OrderType = "exchange market" + OrderTypeExchangeStopLimit OrderType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the OrderType enum. +func (e OrderType) Valid() bool { + switch e { + case OrderTypeExchangeLimit: + return true + case OrderTypeExchangeMarket: + return true + case OrderTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for RiskStatsResponseProductType. +const ( + PerpetualSwapContract RiskStatsResponseProductType = "PerpetualSwapContract" +) + +// Valid indicates whether the value is a known member of the RiskStatsResponseProductType enum. +func (e RiskStatsResponseProductType) Valid() bool { + switch e { + case PerpetualSwapContract: + return true + default: + return false + } +} + +// Defines values for StakingTransactionTransactionType. +const ( + StakingTransactionTransactionTypeAdminCreditAdjustment StakingTransactionTransactionType = "AdminCreditAdjustment" + StakingTransactionTransactionTypeAdminDebitAdjustment StakingTransactionTransactionType = "AdminDebitAdjustment" + StakingTransactionTransactionTypeAdminRedeem StakingTransactionTransactionType = "AdminRedeem" + StakingTransactionTransactionTypeDeposit StakingTransactionTransactionType = "Deposit" + StakingTransactionTransactionTypeInterest StakingTransactionTransactionType = "Interest" + StakingTransactionTransactionTypeRedeem StakingTransactionTransactionType = "Redeem" + StakingTransactionTransactionTypeRedeemPayment StakingTransactionTransactionType = "RedeemPayment" +) + +// Valid indicates whether the value is a known member of the StakingTransactionTransactionType enum. +func (e StakingTransactionTransactionType) Valid() bool { + switch e { + case StakingTransactionTransactionTypeAdminCreditAdjustment: + return true + case StakingTransactionTransactionTypeAdminDebitAdjustment: + return true + case StakingTransactionTransactionTypeAdminRedeem: + return true + case StakingTransactionTransactionTypeDeposit: + return true + case StakingTransactionTransactionTypeInterest: + return true + case StakingTransactionTransactionTypeRedeem: + return true + case StakingTransactionTransactionTypeRedeemPayment: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseSide. +const ( + StopLimitOrderResponseSideBuy StopLimitOrderResponseSide = "buy" + StopLimitOrderResponseSideSell StopLimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseSide enum. +func (e StopLimitOrderResponseSide) Valid() bool { + switch e { + case StopLimitOrderResponseSideBuy: + return true + case StopLimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseType. +const ( + ExchangeStopLimit StopLimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseType enum. +func (e StopLimitOrderResponseType) Valid() bool { + switch e { + case ExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for TradeType. +const ( + TradeTypeBuy TradeType = "buy" + TradeTypeSell TradeType = "sell" +) + +// Valid indicates whether the value is a known member of the TradeType enum. +func (e TradeType) Valid() bool { + switch e { + case TradeTypeBuy: + return true + case TradeTypeSell: + return true + default: + return false + } +} + +// Defines values for TransferStatus. +const ( + TransferStatusComplete TransferStatus = "Complete" + TransferStatusPending TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the TransferStatus enum. +func (e TransferStatus) Valid() bool { + switch e { + case TransferStatusComplete: + return true + case TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for TransferType. +const ( + TransferTypeDeposit TransferType = "Deposit" + TransferTypeWithdrawal TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the TransferType enum. +func (e TransferType) Valid() bool { + switch e { + case TransferTypeDeposit: + return true + case TransferTypeWithdrawal: + return true + default: + return false + } +} + +// Defines values for V2TransferStatus. +const ( + V2TransferStatusAdvanced V2TransferStatus = "Advanced" + V2TransferStatusComplete V2TransferStatus = "Complete" + V2TransferStatusPending V2TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the V2TransferStatus enum. +func (e V2TransferStatus) Valid() bool { + switch e { + case V2TransferStatusAdvanced: + return true + case V2TransferStatusComplete: + return true + case V2TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for V2TransferType. +const ( + AdminCredit V2TransferType = "AdminCredit" + AdminDebit V2TransferType = "AdminDebit" + Deposit V2TransferType = "Deposit" + Reward V2TransferType = "Reward" + Withdrawal V2TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the V2TransferType enum. +func (e V2TransferType) Valid() bool { + switch e { + case AdminCredit: + return true + case AdminDebit: + return true + case Deposit: + return true + case Reward: + return true + case Withdrawal: + return true + default: + return false + } +} + +// Defines values for AddBankJSONBodyType. +const ( + AddBankJSONBodyTypeChecking AddBankJSONBodyType = "checking" + AddBankJSONBodyTypeSavings AddBankJSONBodyType = "savings" +) + +// Valid indicates whether the value is a known member of the AddBankJSONBodyType enum. +func (e AddBankJSONBodyType) Valid() bool { + switch e { + case AddBankJSONBodyTypeChecking: + return true + case AddBankJSONBodyTypeSavings: + return true + default: + return false + } +} + +// Defines values for AddBankCADJSONBodyType. +const ( + AddBankCADJSONBodyTypeChecking AddBankCADJSONBodyType = "checking" + AddBankCADJSONBodyTypeSavings AddBankCADJSONBodyType = "savings" +) + +// Valid indicates whether the value is a known member of the AddBankCADJSONBodyType enum. +func (e AddBankCADJSONBodyType) Valid() bool { + switch e { + case AddBankCADJSONBodyTypeChecking: + return true + case AddBankCADJSONBodyTypeSavings: + return true + default: + return false + } +} + +// Account defines model for Account. +type Account struct { + // AccountId The account ID + AccountId *string `json:"account_id,omitempty"` + + // Created The creation date + Created *string `json:"created,omitempty"` + + // IsDefault Whether the account is the default account + IsDefault *bool `json:"is_default,omitempty"` + + // Name The account name + Name *string `json:"name,omitempty"` +} + +// AddBankResponse defines model for AddBankResponse. +type AddBankResponse struct { + // ReferenceId Reference ID for the new bank addition request. Once received, send in a wire from the requested bank account to verify it and enable withdrawals to that account. + ReferenceId *string `json:"referenceId,omitempty"` + + // Result Status result (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// Address defines model for Address. +type Address struct { + // Address String representation of the cryptocurrency address + Address *string `json:"address,omitempty"` + + // Label If you provided a label when creating the address, it will be echoed back here + Label *string `json:"label,omitempty"` + + // Memo It would be present if applicable, it will be present for cosmos address + Memo *string `json:"memo,omitempty"` + + // Network The blockchain network for the address + Network *string `json:"network,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ApprovedAddress defines model for ApprovedAddress. +type ApprovedAddress struct { + // Address The address on the approved address list. + Address *string `json:"address,omitempty"` + + // CreatedAt UTC timestamp in millisecond of when the address was created. + CreatedAt *string `json:"createdAt,omitempty"` + + // Label The label assigned to the address + Label *string `json:"label,omitempty"` + + // Network The network of the approved address. Network can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Network *string `json:"network,omitempty"` + + // Scope Will return the scope of the address as either "account" or "group" + Scope *string `json:"scope,omitempty"` + + // Status The status of the address that will return as "active", "pending-time" or "pending-mua". The remaining time is exactly 7 days after the initial request. "pending-mua" is for multi-user accounts and will require another administator or fund manager on the account to approve the address. + Status *string `json:"status,omitempty"` +} + +// ApprovedAddressMessage defines model for ApprovedAddressMessage. +type ApprovedAddressMessage struct { + // Message Status or confirmation message for the approved address request or removal. + Message *string `json:"message,omitempty"` + + // Result Result status (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// ApprovedAddressesResponse Response envelope containing the approved withdrawal addresses. +type ApprovedAddressesResponse struct { + // ApprovedAddresses Array of approved addresses on both the account and group level. + ApprovedAddresses *[]ApprovedAddress `json:"approvedAddresses,omitempty"` +} + +// Balance defines model for Balance. +type Balance struct { + // UnderscoreTimestamp Server-side monotonically increasing clock value as an ISO 8601 timestamp. Clients can use this value to detect and filter out stale responses that may occur due to load balancing or potential stale servers. + UnderscoreTimestamp *time.Time `json:"_timestamp,omitempty"` + + // Amount The confirmed balance for the currency (also referred to as `confirmedBalance`). For crypto withdrawals, this value is **not** reduced until the withdrawal has been confirmed on the blockchain. This delay protects against blockchain reorganizations. Use the `available` field instead if you need balances that immediately reflect holds. + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Available The amount available for trading. This value is reduced **immediately** when an order hold or withdrawal hold is placed, making it the recommended field for tracking real-time spendable balances. + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The amount available for withdrawal + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Currency The currency symbol + Currency *string `json:"currency,omitempty"` + + // PendingDeposit The amount pending deposit + PendingDeposit *openapi_types.DecimalNumber `json:"pendingDeposit,omitempty"` + + // PendingWithdrawal The amount pending withdrawal + PendingWithdrawal *openapi_types.DecimalNumber `json:"pendingWithdrawal,omitempty"` + Type *BalanceType `json:"type,omitempty"` +} + +// BalanceType defines model for Balance.Type. +type BalanceType string + +// CancelAllOrdersBySessionRequest defines model for CancelAllOrdersBySessionRequest. +type CancelAllOrdersBySessionRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/session" + Request string `json:"request"` +} + +// CancelAllOrdersRequest defines model for CancelAllOrdersRequest. +type CancelAllOrdersRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/all" + Request string `json:"request"` +} + +// CancelAllResult defines model for CancelAllResult. +type CancelAllResult struct { + // Details cancelledOrders/cancelRejects with IDs of both + Details *struct { + CancelRejects *[]int64 `json:"cancelRejects,omitempty"` + CancelledOrders *[]int64 `json:"cancelledOrders,omitempty"` + } `json:"details,omitempty"` + Result *string `json:"result,omitempty"` +} + +// CancelOrderRequest defines model for CancelOrderRequest. +type CancelOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order ID given by `/order/new` + OrderId uint64 `json:"order_id"` + + // Request The literal string "/v1/order/cancel" + Request string `json:"request"` +} + +// CancelOrderResponse defines model for CancelOrderResponse. +type CancelOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Reason *CancelOrderResponseReason `json:"reason,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *CancelOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *CancelOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// CancelOrderResponseReason defines model for CancelOrderResponse.Reason. +type CancelOrderResponseReason string + +// CancelOrderResponseSide defines model for CancelOrderResponse.Side. +type CancelOrderResponseSide string + +// CancelOrderResponseType defines model for CancelOrderResponse.Type. +type CancelOrderResponseType string + +// Candle defines model for Candle. +type Candle = []float64 + +// CandleResponse defines model for CandleResponse. +type CandleResponse = []Candle + +// ClearingOrder defines model for ClearingOrder. +type ClearingOrder struct { + // Amount The order amount + Amount *string `json:"amount,omitempty"` + + // ClearingId The clearing ID + ClearingId *string `json:"clearing_id,omitempty"` + + // IsConfirmed Whether the order is confirmed + IsConfirmed *bool `json:"is_confirmed,omitempty"` + + // Price The order price + Price *string `json:"price,omitempty"` + Side *ClearingOrderSide `json:"side,omitempty"` + + // Status The order status + Status *string `json:"status,omitempty"` + + // Symbol The trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms The timestamp in milliseconds + Timestampms *int64 `json:"timestampms,omitempty"` +} + +// ClearingOrderSide defines model for ClearingOrder.Side. +type ClearingOrderSide string + +// CustodyFeeTransfer defines model for CustodyFeeTransfer. +type CustodyFeeTransfer struct { + // Eid Custody fee event id + Eid *int64 `json:"eid,omitempty"` + + // EventType Custody fee event type + EventType *string `json:"eventType,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // TxTime Time of Custody fee record in milliseconds + TxTime *int64 `json:"txTime,omitempty"` +} + +// ErrorResponse defines model for ErrorResponse. +type ErrorResponse struct { + // Message Detailed error message + Message *string `json:"message,omitempty"` + + // Reason A short description + Reason *string `json:"reason,omitempty"` + + // Result Error + Result *string `json:"result,omitempty"` +} + +// FeeEstimateRequest defines model for FeeEstimateRequest. +type FeeEstimateRequest struct { + // Account The name of the account within the subaccount group. + Account string `json:"account"` + + // Address Standard string format of cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v1/withdraw/{currencyCodeLowerCase}/feeEstimate` where `:currencyCodeLowerCase` is replaced with the currency code of a supported crypto-currency, e.g. `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateResponse defines model for FeeEstimateResponse. +type FeeEstimateResponse struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated gas fee + Fee *string `json:"fee,omitempty"` + + // IsOverride Value that shows if an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total nunber of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals left to use + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeeEstimateV2Request defines model for FeeEstimateV2Request. +type FeeEstimateV2Request struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Address Standard string format of the destination cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Memo It would be present if applicable, it will be present for cosmos address. + Memo *string `json:"memo,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v2/withdraw/{network}/{ticker}/feeEstimate` where `{network}` is the blockchain network (e.g. `ethereum`, `bitcoin`, `solana`) and `{ticker}` is the currency code (e.g. `eth`, `btc`, `sol`). See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateV2Response defines model for FeeEstimateV2Response. +type FeeEstimateV2Response struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated withdrawal fee as a decimal amount + Fee *openapi_types.DecimalNumber `json:"fee,omitempty"` + + // IsOverride Whether an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total number of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals remaining + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeePromos defines model for FeePromos. +type FeePromos struct { + // Symbols Symbols that currently have fee promos + Symbols *[]string `json:"symbols,omitempty"` +} + +// FundingAmountResponse defines model for FundingAmountResponse. +type FundingAmountResponse struct { + // Amount The dollar amount for a Long 1 position held in the symbol for funding period (1 hour) + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // EstimatedFundingAmount The estimated dollar amount for a Long 1 position held in the symbol for next funding period (1 hour) + EstimatedFundingAmount *openapi_types.DecimalNumber `json:"estimatedFundingAmount,omitempty"` + + // FundingDateTime UTC date time in format `yyyy-MM-ddThh:mm:ss.SSSZ` format + FundingDateTime *string `json:"fundingDateTime,omitempty"` + + // FundingTimestampMilliSecs Current funding amount Epoc time. + FundingTimestampMilliSecs *int64 `json:"fundingTimestampMilliSecs,omitempty"` + + // NextFundingTimestamp Next funding amount Epoc time. + NextFundingTimestamp *int64 `json:"nextFundingTimestamp,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` +} + +// FundingPayment defines model for FundingPayment. +type FundingPayment struct { + // EventType Event type + EventType FundingPaymentEventType `json:"eventType"` + HourlyFundingTransfer FundingTransfer `json:"hourlyFundingTransfer"` +} + +// FundingPaymentEventType Event type +type FundingPaymentEventType string + +// FundingPaymentReportItem defines model for FundingPaymentReportItem. +type FundingPaymentReportItem struct { + // Action Credit or Debit + Action FundingPaymentReportItemAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType FundingPaymentReportItemEventType `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingPaymentReportItemAction Credit or Debit +type FundingPaymentReportItemAction string + +// FundingPaymentReportItemEventType Event type +type FundingPaymentReportItemEventType string + +// FundingTransfer defines model for FundingTransfer. +type FundingTransfer struct { + // Action Credit or Debit + Action FundingTransferAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType string `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingTransferAction Credit or Debit +type FundingTransferAction string + +// FxRate defines model for FxRate. +type FxRate struct { + // AsOf timestamp + AsOf *TimestampType `json:"asOf,omitempty"` + + // Benchmark The market for which the retrieved price applies to + Benchmark *string `json:"benchmark,omitempty"` + + // FxPair The requested currency pair + FxPair *string `json:"fxPair,omitempty"` + + // Provider The market data provider + Provider *string `json:"provider,omitempty"` + + // Rate The exchange rate + Rate *float64 `json:"rate,omitempty"` +} + +// Heartbeat defines model for Heartbeat. +type Heartbeat struct { + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce *Heartbeat_Nonce `json:"nonce,omitempty"` + + // Request The literal string `/v1/heartbeat` + Request *string `json:"request,omitempty"` +} + +// HeartbeatNonce0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `'1495127793'` | `POST` only | +// | string (milliseconds) | `'1495127793000'` | `POST` only | +type HeartbeatNonce0 = string + +// HeartbeatNonce1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type HeartbeatNonce1 = int64 + +// Heartbeat_Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Heartbeat_Nonce struct { + union json.RawMessage +} + +// InstantQuote defines model for InstantQuote. +type InstantQuote struct { + // DepositFee The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + DepositFee *string `json:"depositFee,omitempty"` + + // DepositFeeCurrency Currency in which `depositFee` is taken + DepositFeeCurrency *string `json:"depositFeeCurrency,omitempty"` + + // Fee The fee quantity to be taken for the order upon execution + Fee *string `json:"fee,omitempty"` + + // FeeCurrency The currency label for the order + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // MaxAgeMs Number of milliseconds until this quote price expires. Once expired, you will need to request a new quote + MaxAgeMs *int `json:"maxAgeMs,omitempty"` + + // Pair The symbol passed in the quote request + Pair *string `json:"pair,omitempty"` + + // Price The quoted price of the asset. This will not change when attempting execution + Price *string `json:"price,omitempty"` + + // PriceCurrency The currency in which the order is priced. Matches `CCY2` in the symbol + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // Quantity The quantity of the asset to be bought or sold + Quantity *string `json:"quantity,omitempty"` + + // QuantityCurrency The currency label for the `quantity` field. Matches `CCY1` in the symbol + QuantityCurrency *string `json:"quantityCurrency,omitempty"` + + // QuoteId Unique ID for the quote. This is used in the execution of the order + QuoteId *int64 `json:"quoteId,omitempty"` + + // Side Either "buy" or "sell" + Side *InstantQuoteSide `json:"side,omitempty"` + + // TotalSpend Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + TotalSpend *string `json:"totalSpend,omitempty"` + + // TotalSpendCurrency Currency of the `totalSpend` to be spent on the order + TotalSpendCurrency *string `json:"totalSpendCurrency,omitempty"` +} + +// InstantQuoteSide Either "buy" or "sell" +type InstantQuoteSide string + +// InterestRateInfo defines model for InterestRateInfo. +type InterestRateInfo struct { + // Interval The time interval for the rate (currently only "hour" is supported) + Interval InterestRateInfoInterval `json:"interval"` + + // Rate The interest rate as a decimal string + Rate string `json:"rate"` +} + +// InterestRateInfoInterval The time interval for the rate (currently only "hour" is supported) +type InterestRateInfoInterval string + +// LimitOrderResponse defines model for LimitOrderResponse. +type LimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *LimitOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *LimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// LimitOrderResponseSide defines model for LimitOrderResponse.Side. +type LimitOrderResponseSide string + +// LimitOrderResponseType defines model for LimitOrderResponse.Type. +type LimitOrderResponseType string + +// LiquidationRisk defines model for LiquidationRisk. +type LiquidationRisk struct { + // LiquidationPrice The estimated price at which liquidation would occur (optional, may not be present for all positions) + LiquidationPrice *MoneyAmount `json:"liquidationPrice,omitempty"` + + // LossPercentage The percentage loss from current value that would trigger liquidation, formatted as decimal (e.g., "0.1550" = 15.50%) + LossPercentage string `json:"lossPercentage"` +} + +// MarginAccountSummary defines model for MarginAccountSummary. +type MarginAccountSummary struct { + // AvailableCollateral The amount of collateral available for new positions or withdrawals + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased with available collateral + BuyingPower MoneyAmount `json:"buyingPower"` + + // InterestRate Current interest rate on borrowed amounts (only present if borrows exist) + InterestRate *InterestRateInfo `json:"interestRate,omitempty"` + + // Leverage The current leverage ratio (notionalValue / marginAssetValue) + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if positions exist) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account that can contribute to funding positions + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold with available collateral + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed across all currencies + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MarginInterestRate defines model for MarginInterestRate. +type MarginInterestRate struct { + // BorrowRate The hourly borrow rate as a decimal + BorrowRate string `json:"borrowRate"` + + // BorrowRateAnnual The annualized borrow rate (daily rate × 365) + BorrowRateAnnual string `json:"borrowRateAnnual"` + + // BorrowRateDaily The daily borrow rate (hourly rate × 24) + BorrowRateDaily string `json:"borrowRateDaily"` + + // Currency The currency code (e.g., "BTC", "ETH", "USD") + Currency string `json:"currency"` + + // LastUpdated Unix timestamp in milliseconds when the rate was last updated + LastUpdated int64 `json:"lastUpdated"` +} + +// MarginOrderPreview defines model for MarginOrderPreview. +type MarginOrderPreview struct { + // Postorder Margin risk statistics after the order would be executed + Postorder MarginRiskStats `json:"postorder"` + + // Preorder Margin risk statistics before the order would be executed + Preorder MarginRiskStats `json:"preorder"` +} + +// MarginRatesResponse defines model for MarginRatesResponse. +type MarginRatesResponse struct { + // Rates Array of interest rates for all borrowable currencies + Rates []MarginInterestRate `json:"rates"` +} + +// MarginResponse defines model for MarginResponse. +type MarginResponse struct { + // AvailableMargin The difference between the `margin_assets_value` and `initial_margin`. + AvailableMargin *string `json:"available_margin,omitempty"` + + // BuyingPower The amount of that product the account could purchase based on current `initial_margin` and `margin_assets_value`. + BuyingPower *string `json:"buying_power,omitempty"` + + // EstimatedLiquidationPrice The estimated price for the asset at which liquidation would occur. + EstimatedLiquidationPrice *string `json:"estimated_liquidation_price,omitempty"` + + // InitialMargin The $ amount that is being required by the accounts current positions and open orders. + InitialMargin *string `json:"initial_margin,omitempty"` + + // InitialMarginPositions The contribution to `initial_margin` from open positions. + InitialMarginPositions *string `json:"initial_margin_positions,omitempty"` + + // Leverage The ratio of Notional Value to Margin Assets Value. + Leverage *string `json:"leverage,omitempty"` + + // MarginAssetsValue The $ equivalent value of all the assets available in the current trading account that can contribute to funding a derivatives position. + MarginAssetsValue *string `json:"margin_assets_value,omitempty"` + + // MarginMaintenanceLimit The minimum amount of `margin_assets_value` required before the account is moved to liquidation status. + MarginMaintenanceLimit *string `json:"margin_maintenance_limit,omitempty"` + + // NotionalValue The $ value of the current position. + NotionalValue *string `json:"notional_value,omitempty"` + + // ReservedMargin The contribution to `initial_margin` from open orders. + ReservedMargin *string `json:"reserved_margin,omitempty"` + + // ReservedMarginBuys The contribution to `initial_margin` from open BUY orders. + ReservedMarginBuys *string `json:"reserved_margin_buys,omitempty"` + + // ReservedMarginSells The contribution to `initial_margin` from open SELL orders. + ReservedMarginSells *string `json:"reserved_margin_sells,omitempty"` + + // SellingPower The amount of that product the account could sell based on current `initial_margin` and `margin_assets_value`. + SellingPower *string `json:"selling_power,omitempty"` +} + +// MarginRiskStats defines model for MarginRiskStats. +type MarginRiskStats struct { + // AvailableCollateral The amount of collateral available for new positions + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased + BuyingPower MoneyAmount `json:"buyingPower"` + + // Leverage The leverage ratio + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if applicable) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MoneyAmount defines model for MoneyAmount. +type MoneyAmount struct { + // Currency The currency code (e.g., "USD", "BTC", "ETH") + Currency string `json:"currency"` + + // Value The amount in the specified currency + Value string `json:"value"` +} + +// MyTrade defines model for MyTrade. +type MyTrade struct { + Aggressor *bool `json:"aggressor,omitempty"` + Amount *string `json:"amount,omitempty"` + Break *MyTradeBreak `json:"break,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + FeeAmount *string `json:"fee_amount,omitempty"` + FeeCurrency *string `json:"fee_currency,omitempty"` + IsAuctionFill *bool `json:"is_auction_fill,omitempty"` + OrderId *string `json:"order_id,omitempty"` + Price *string `json:"price,omitempty"` + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *MyTradeType `json:"type,omitempty"` +} + +// MyTradeBreak defines model for MyTrade.Break. +type MyTradeBreak string + +// MyTradeType defines model for MyTrade.Type. +type MyTradeType string + +// MyTradesRequest defines model for MyTradesRequest. +type MyTradesRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // LimitTrades The maximum number of trades to return. Default is 50, max is 500. + LimitTrades *int `json:"limit_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) to retrieve trades for + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// NetworkAssets defines model for NetworkAssets. +type NetworkAssets struct { + // Assets Alphabetically sorted array of enabled asset/token codes available on this network. Assets include both exchange-tradable and custody-supported tokens. + Assets *[]string `json:"assets,omitempty"` + + // Network The blockchain network identifier. + Network *string `json:"network,omitempty"` +} + +// NetworkToken defines model for NetworkToken. +type NetworkToken struct { + // Network Array of supported blockchain networks for the token. Many tokens (especially stablecoins like USDC, USDT) are available on multiple networks. + // + // Supported networks include: `bitcoin`, `ethereum`, `solana`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + Network *[]string `json:"network,omitempty"` + + // Token The requested token identifier. + Token *string `json:"token,omitempty"` +} + +// NewOrderRequest defines model for NewOrderRequest. +type NewOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Amount Quoted decimal amount to purchase + Amount string `json:"amount"` + + // ClientOrderId *Recommended*. A [client-specified order id](/client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // MarginOrder Set to `true` to place this order on a margin account using borrowed funds. Defaults to `false`. Only available for margin-enabled accounts. See [Margin Trading](/margin/account-summary) for details. + MarginOrder *bool `json:"margin_order,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce int64 `json:"nonce"` + + // Options An optional array containing at most one supported order execution option. See Order execution options for details. + Options *[]NewOrderRequestOptions `json:"options,omitempty"` + + // Price Quoted decimal amount to spend per unit + Price string `json:"price"` + + // Request The literal string "/v1/order/new" + Request string `json:"request"` + Side NewOrderRequestSide `json:"side"` + + // StopPrice The price to trigger a stop-limit order. Only available for stop-limit orders. + StopPrice *string `json:"stop_price,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) for the new order + Symbol string `json:"symbol"` + + // Type The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. + Type NewOrderRequestType `json:"type"` +} + +// NewOrderRequestOptions defines model for NewOrderRequest.Options. +type NewOrderRequestOptions string + +// NewOrderRequestSide defines model for NewOrderRequest.Side. +type NewOrderRequestSide string + +// NewOrderRequestType The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. +type NewOrderRequestType string + +// Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Nonce struct { + union json.RawMessage +} + +// Nonce1 defines model for . +type Nonce1 = int64 + +// NotionalBalance defines model for NotionalBalance. +type NotionalBalance struct { + // Amount The current balance + Amount *string `json:"amount,omitempty"` + + // AmountNotional Amount, in notional + AmountNotional *string `json:"amountNotional,omitempty"` + + // Available The amount that is available to trade + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal The amount that is available to withdraw + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // AvailableForWithdrawalNotional AvailableForWithdrawal, in notional + AvailableForWithdrawalNotional *string `json:"availableForWithdrawalNotional,omitempty"` + + // AvailableNotional Available, in notional + AvailableNotional *string `json:"availableNotional,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` +} + +// NotionalVolume defines model for NotionalVolume. +type NotionalVolume struct { + ApiAuctionFeeBps *int `json:"api_auction_fee_bps,omitempty"` + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiNotional30dVolume *string `json:"api_notional_30d_volume,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Date *openapi_types.Date `json:"date,omitempty"` + FeeTier *struct { + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Tier *string `json:"tier,omitempty"` + } `json:"fee_tier,omitempty"` + FixAuctionFeeBps *int `json:"fix_auction_fee_bps,omitempty"` + FixMakerFeeBps *int `json:"fix_maker_fee_bps,omitempty"` + FixTakerFeeBps *int `json:"fix_taker_fee_bps,omitempty"` + LastUpdatedMs *int64 `json:"last_updated_ms,omitempty"` + Notional1dVolume *[]struct { + // Date UTC date in `yyyy-MM-dd` format + Date *string `json:"date,omitempty"` + + // NotionalVolume Notional volume value in USD for this single day + NotionalVolume *string `json:"notional_volume,omitempty"` + } `json:"notional_1d_volume,omitempty"` + Notional30dVolume *string `json:"notional_30d_volume,omitempty"` + WebAuctionFeeBps *int `json:"web_auction_fee_bps,omitempty"` + WebMakerFeeBps *int `json:"web_maker_fee_bps,omitempty"` + WebTakerFeeBps *int `json:"web_taker_fee_bps,omitempty"` +} + +// OpenPosition defines model for OpenPosition. +type OpenPosition struct { + // AverageCost The average price of the current position. + AverageCost *string `json:"average_cost,omitempty"` + + // InstrumentType The type of instrument. Either "spot" or "perp". + InstrumentType *string `json:"instrument_type,omitempty"` + + // MarkPrice The current Mark Price for the Asset or the position. + MarkPrice *string `json:"mark_price,omitempty"` + + // NotionalValue The value of position; calculated as (`quantity` * `mark_price`). Value will be negative for shorts. + NotionalValue *string `json:"notional_value,omitempty"` + + // Quantity The position size. Value will be negative for shorts. + Quantity *string `json:"quantity,omitempty"` + + // RealisedPnl The current P&L that has been realised from the position. + RealisedPnl *string `json:"realised_pnl,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) of the order. + Symbol *string `json:"symbol,omitempty"` + + // UnrealisedPnl Current Mark to Market value of the positions. + UnrealisedPnl *string `json:"unrealised_pnl,omitempty"` +} + +// Order defines model for Order. +type Order struct { + // AvgExecutionPrice The average price at which this order as been executed so far. 0 if the order has not been executed at all. + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + + // ClientOrderId An optional [client-specified order id](/client-order-id#client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // ExecutedAmount The amount of the order that has been filled. + ExecutedAmount *string `json:"executed_amount,omitempty"` + + // IsCancelled `true` if the order has been canceled. Note the spelling, "cancelled" instead of "canceled". This is for compatibility reasons. + IsCancelled *bool `json:"is_cancelled,omitempty"` + + // IsHidden Will always return `false`. + IsHidden *bool `json:"is_hidden,omitempty"` + + // IsLive `true` if the order is active on the book (has remaining quantity and has not been canceled) + IsLive *bool `json:"is_live,omitempty"` + + // Options An array containing at most one supported order execution option. See [Order execution options](/rest/orders#create-new-order) for details. + Options *[]string `json:"options,omitempty"` + + // OrderId The order id + OrderId *string `json:"order_id,omitempty"` + + // OriginalAmount The originally submitted amount of the order. + OriginalAmount *string `json:"original_amount,omitempty"` + + // Price The price the order was issued at + Price *string `json:"price,omitempty"` + + // Reason Populated with the reason your order was canceled, if available. + Reason *string `json:"reason,omitempty"` + + // RemainingAmount The amount of the order that has not been filled. + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *OrderSide `json:"side,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums#symbols-and-minimums) of the order + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Trades Contains an array of JSON objects with trade details. + Trades *[]struct { + // Aggressor If `true`, this order was the taker in the trade + Aggressor *bool `json:"aggressor,omitempty"` + + // Amount The quantity that was executed + Amount *string `json:"amount,omitempty"` + + // Break Will only be present if the trade is broken. See `Break Types` below for more information. + Break *string `json:"break,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The amount charged + FeeAmount *string `json:"fee_amount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"fee_currency,omitempty"` + + // OrderId The order that this trade executed against + OrderId *string `json:"order_id,omitempty"` + + // Price The price that the execution happened at + Price *string `json:"price,omitempty"` + + // Tid Unique identifier for the trade + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type Will be either "Buy" or "Sell", indicating the side of the original order + Type *OrderTradesType `json:"type,omitempty"` + } `json:"trades,omitempty"` + + // Type Description of the order + Type *OrderType `json:"type,omitempty"` + + // WasForced Will always be `false`. + WasForced *bool `json:"was_forced,omitempty"` +} + +// OrderSide defines model for Order.Side. +type OrderSide string + +// OrderTradesType Will be either "Buy" or "Sell", indicating the side of the original order +type OrderTradesType string + +// OrderType Description of the order +type OrderType string + +// OrderBook defines model for OrderBook. +type OrderBook struct { + // Asks The ask price levels currently on the book. These are offers to sell at a given price. + Asks *[]OrderBookEntry `json:"asks,omitempty"` + + // Bids The bid price levels currently on the book. These are offers to buy at a given price. + Bids *[]OrderBookEntry `json:"bids,omitempty"` +} + +// OrderBookEntry defines model for OrderBookEntry. +type OrderBookEntry struct { + // Amount The total quantity remaining at the price + Amount *string `json:"amount,omitempty"` + + // Price The price + Price *string `json:"price,omitempty"` + + // Timestamp **DO NOT USE** - this field is included for compatibility reasons only and is just populated with a dummy value. + Timestamp *string `json:"timestamp,omitempty"` +} + +// OrderStatusRequest defines model for OrderStatusRequest. +type OrderStatusRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // ClientOrderId The `client_order_id` used when placing the order. `client_order_id` cannot be used in combination with `order_id` + ClientOrderId *string `json:"client_order_id,omitempty"` + + // IncludeTrades Either `True` or `False`. If `True` the endpoint will return individual trade details of all fills from the order. + IncludeTrades *bool `json:"include_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order id to get information on. The `order_id` represents a whole number and is transmitted as an unsigned 64-bit integer in JSON format. `order_id` cannot be used in combination with `client_order_id`. + OrderId uint64 `json:"order_id"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// PaymentMethodBalance defines model for PaymentMethodBalance. +type PaymentMethodBalance struct { + // Amount Total account balance for currency. + Amount *string `json:"amount,omitempty"` + + // Available Total amount available for trading + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal Total amount available for withdrawal + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // Currency Symbol for fiat balance. + Currency *string `json:"currency,omitempty"` + + // Type Account type. Will always be `exchange` + Type *string `json:"type,omitempty"` +} + +// PaymentMethodBank defines model for PaymentMethodBank. +type PaymentMethodBank struct { + // Bank Name of bank account + Bank *string `json:"bank,omitempty"` + + // BankId Unique identifier for bank account + BankId *string `json:"bankId,omitempty"` +} + +// PaymentMethodsResponse defines model for PaymentMethodsResponse. +type PaymentMethodsResponse struct { + // Balances Array of JSON objects with available fiat currencies and their balances. + Balances *[]PaymentMethodBalance `json:"balances,omitempty"` + + // Banks Array of JSON objects with banking information + Banks *[]PaymentMethodBank `json:"banks,omitempty"` +} + +// PriceFeedResponse defines model for PriceFeedResponse. +type PriceFeedResponse = []struct { + // Pair Trading pair symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Pair *string `json:"pair,omitempty"` + + // PercentChange24h 24 hour change in price of the pair on the Gemini order book + PercentChange24h *string `json:"percentChange24h,omitempty"` + + // Price Current price of the pair on the Gemini order book + Price *string `json:"price,omitempty"` +} + +// Quantity defines model for Quantity. +type Quantity struct { + // Currency The currency code of the quantity. + Currency string `json:"currency"` + + // Value The value of the quantity. + Value string `json:"value"` +} + +// RevokeOauthTokenResponse defines model for RevokeOauthTokenResponse. +type RevokeOauthTokenResponse struct { + // Message A message that indicates the token has been revoked for the account + Message *string `json:"message,omitempty"` +} + +// RiskStatsResponse defines model for RiskStatsResponse. +type RiskStatsResponse struct { + // IndexPrice Current index price at the time of request + IndexPrice *string `json:"index_price,omitempty"` + + // MarkPrice Current mark price at the time of request + MarkPrice *string `json:"mark_price,omitempty"` + + // OpenInterest string representation of decimal value of open interest + OpenInterest *string `json:"open_interest,omitempty"` + + // OpenInterestNotional string representation of decimal value of open interest notional + OpenInterestNotional *string `json:"open_interest_notional,omitempty"` + + // ProductType Contract type for which the symbol data is fetched + ProductType *RiskStatsResponseProductType `json:"product_type,omitempty"` +} + +// RiskStatsResponseProductType Contract type for which the symbol data is fetched +type RiskStatsResponseProductType string + +// RoleResponse defines model for RoleResponse. +type RoleResponse struct { + // CounterpartyId _Only returned for master-level API keys_. The Gemini clearing counterparty ID associated with the API key making the request. + CounterpartyId *string `json:"counterparty_id,omitempty"` + + // IsAccountAdmin _Only returned for master-level API keys_.`True` if the Administrator role is assigned to the API keys. `False` otherwise. + IsAccountAdmin *bool `json:"isAccountAdmin,omitempty"` + + // IsAuditor `True` if the Auditor role is assigned to the API keys. `False` otherwise. + IsAuditor bool `json:"isAuditor"` + + // IsFundManager `True` if the Fund Manager role is assigned to the API keys. `False` otherwise. + IsFundManager bool `json:"isFundManager"` + + // IsTrader `True` if the Trader role is assigned to the API keys. `False` otherwise. + IsTrader bool `json:"isTrader"` +} + +// StakingBalance defines model for StakingBalance. +type StakingBalance struct { + // Available The amount that is available to trade + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The Staking amount that is available to redeem to exchange account + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Balance The current Staking balance + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + BalanceByProvider *map[string]struct { + // Balance The current Staking balance per providerId + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + } `json:"balanceByProvider,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` + + // Type Will always be "Staking" + Type *string `json:"type,omitempty"` +} + +// StakingDeposit defines model for StakingDeposit. +type StakingDeposit struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rates A JSON object including one or many rates. If more than one rate it would be an array of rates. + Rates *struct { + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *int `json:"rate,omitempty"` + } `json:"rates,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StakingHistory defines model for StakingHistory. +type StakingHistory struct { + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + Transactions *[]StakingTransaction `json:"transactions,omitempty"` +} + +// StakingRate defines model for StakingRate. +type StakingRate struct { + // ApyPct Staking interest APY (Expressed as a percentage derived from the rate and rounded to 1/10th of a percent.) + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // DepositUsdLimit Maximum new amount in USD notional of this crypto that can participate in Gemini Staking per account per month + DepositUsdLimit *int `json:"depositUsdLimit,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *openapi_types.DecimalNumber `json:"rate,omitempty"` + + // RatePct `rate` expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRateProvider Currency Symbol Keys +type StakingRateProvider struct { + CurrencySymbol *StakingRate `json:"currency_symbol,omitempty"` +} + +// StakingRateResponse Provider UUID Keys +type StakingRateResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRateProvider `json:"provider_uuid,omitempty"` +} + +// StakingRewardPeriod defines model for StakingRewardPeriod. +type StakingRewardPeriod struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // ApyPct Staking reward rate expressed as an APY at time of accrual. Interest on Staking balances compounds daily based on the simple rate which is available from `/v1/staking/rates/` + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // FirstAccrualAt Time of first accrual. In iso datetime with timezone format + FirstAccrualAt *string `json:"firstAccrualAt,omitempty"` + + // LastAccrualAt Time of last accrual. In iso datetime with timezone format + LastAccrualAt *string `json:"lastAccrualAt,omitempty"` + + // NumberOfAccruals Number of accruals in the specific aggregate, typically one per day. If the rate is adjusted, new accruals are added. + NumberOfAccruals *int `json:"numberOfAccruals,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePct Rate expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRewards defines model for StakingRewards. +type StakingRewards struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePeriods Array of JSON objects with period accrual information + RatePeriods *[]StakingRewardPeriod `json:"ratePeriods,omitempty"` +} + +// StakingRewardsProvider Currency Symbol Keys +type StakingRewardsProvider struct { + CurrencySymbol *StakingRewards `json:"currency_symbol,omitempty"` +} + +// StakingRewardsResponse Provider UUID Keys +type StakingRewardsResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRewardsProvider `json:"provider_uuid,omitempty"` +} + +// StakingTransaction defines model for StakingTransaction. +type StakingTransaction struct { + // Amount The amount that is defined by the transactionType above + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountCurrency Currency code + AmountCurrency *string `json:"amountCurrency,omitempty"` + + // DateTime timestamp + DateTime *TimestampType `json:"dateTime,omitempty"` + + // PriceAmount Current market price of the underlying token at the time of the reward + PriceAmount *openapi_types.DecimalNumber `json:"priceAmount,omitempty"` + + // PriceCurrency A supported three-letter fiat currency code, e.g. usd + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` + + // TransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment + TransactionType *StakingTransactionTransactionType `json:"transactionType,omitempty"` +} + +// StakingTransactionTransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment +type StakingTransactionTransactionType string + +// StakingWithdrawal defines model for StakingWithdrawal. +type StakingWithdrawal struct { + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountPaidSoFar The amount redeemed successfully + AmountPaidSoFar *openapi_types.DecimalNumber `json:"amountPaidSoFar,omitempty"` + + // AmountRemaining The amount pending to be redeemed + AmountRemaining *openapi_types.DecimalNumber `json:"amountRemaining,omitempty"` + + // Currency Currency code + Currency *string `json:"currency,omitempty"` + + // RequestInitiated In ISO datetime with timezone format + RequestInitiated *string `json:"requestInitiated,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StopLimitOrderResponse defines model for StopLimitOrderResponse. +type StopLimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Side *StopLimitOrderResponseSide `json:"side,omitempty"` + StopPrice *string `json:"stop_price,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *StopLimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// StopLimitOrderResponseSide defines model for StopLimitOrderResponse.Side. +type StopLimitOrderResponseSide string + +// StopLimitOrderResponseType defines model for StopLimitOrderResponse.Type. +type StopLimitOrderResponseType string + +// SymbolDetails defines model for SymbolDetails. +type SymbolDetails struct { + // BaseCurrency CCY1 or the top currency. (i.e `BTC` in `BTCUSD`) + BaseCurrency *string `json:"base_currency,omitempty"` + + // ContractPriceCurrency CCY2 or the quote currency for spot instrument (i.e. `USD` in `BTCUSD`) + // Or collateral currency of the contract in case of perpetual swap instrument. + ContractPriceCurrency *string `json:"contract_price_currency,omitempty"` + + // ContractType `vanilla` / `linear` / `inverse` where `vanilla` is for spot + // while `linear` is for perpetual swap and `inverse` is a special case perpetual swap where the perpetual contract will be settled in base currency. + ContractType *string `json:"contract_type,omitempty"` + + // MinOrderSize The minimum order size in `base_currency` units (i.e `0.00001`) + MinOrderSize *string `json:"min_order_size,omitempty"` + + // ProductType Instrument type `spot` / `swap` -- where `swap` signifies `perpetual swap`. + ProductType *string `json:"product_type,omitempty"` + + // QuoteCurrency CCY2 or the quote currency. (i.e `USD` in `BTCUSD`) + QuoteCurrency *string `json:"quote_currency,omitempty"` + + // QuoteIncrement The number of decimal places in the `quote_currency` (i.e `0.01`) + QuoteIncrement *openapi_types.DecimalNumber `json:"quote_increment,omitempty"` + + // Status Status of the current order book. Can be `open`, `closed`, `cancel_only`, `post_only`, `limit_only`. + Status *string `json:"status,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` + + // TickSize The number of decimal places in the `base_currency`. (i.e `1e-8`) + TickSize *openapi_types.DecimalNumber `json:"tick_size,omitempty"` + + // WrapEnabled When `True`, symbol can be wrapped using this endpoint: + // `POST https://api.gemini.com/v1/wrap/:symbol` + WrapEnabled *bool `json:"wrap_enabled,omitempty"` +} + +// Ticker defines model for Ticker. +type Ticker struct { + // Ask The lowest ask currently available + Ask *string `json:"ask,omitempty"` + + // Bid The highest bid currently available + Bid *string `json:"bid,omitempty"` + + // Last The price of the last executed trade + Last *string `json:"last,omitempty"` + + // Volume Information about the 24 hour volume on the exchange. See properties below + Volume *struct { + // PriceSymbol The volume denominated in the price currency + PriceSymbol *string `json:"price_symbol,omitempty"` + + // QuantitySymbol The volume denominated in the quantity currency + QuantitySymbol *string `json:"quantity_symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + } `json:"volume,omitempty"` +} + +// TickerInfo defines model for TickerInfo. +type TickerInfo struct { + // Ask Current best offer + Ask *string `json:"ask,omitempty"` + + // Bid Current best bid + Bid *string `json:"bid,omitempty"` + + // Changes Hourly prices descending for past 24 hours + Changes *[]string `json:"changes,omitempty"` + + // Close Close price (most recent trade) + Close *string `json:"close,omitempty"` + + // High High price from 24 hours ago + High *string `json:"high,omitempty"` + + // Low Low price from 24 hours ago + Low *string `json:"low,omitempty"` + + // Open Open price from 24 hours ago + Open *string `json:"open,omitempty"` + + // Symbol The trading pair symbol + Symbol *string `json:"symbol,omitempty"` +} + +// TimestampType timestamp +type TimestampType struct { + union json.RawMessage +} + +// TimestampType0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `1495127793` | `POST` only | +// | string (milliseconds) | `1495127793000` | `POST` only | +type TimestampType0 = string + +// TimestampType1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type TimestampType1 = int64 + +// Trade defines model for Trade. +type Trade struct { + // Amount The amount that was traded + Amount *string `json:"amount,omitempty"` + + // Broken Whether the trade was broken or not. Broken trades will not be displayed by default; use the `include_breaks` to display them. + Broken *bool `json:"broken,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // Price The price the trade was executed at + Price *string `json:"price,omitempty"` + + // Tid The trade ID number + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type - `buy` means that an ask was removed from the book by an incoming buy order. + // - `sell` means that a bid was removed from the book by an incoming sell order. + Type *TradeType `json:"type,omitempty"` +} + +// TradeType - `buy` means that an ask was removed from the book by an incoming buy order. +// - `sell` means that a bid was removed from the book by an incoming sell order. +type TradeType string + +// TradeVolume defines model for TradeVolume. +type TradeVolume struct { + BaseCurrency *string `json:"base_currency,omitempty"` + BuyMakerBase *string `json:"buy_maker_base,omitempty"` + BuyMakerCount *int `json:"buy_maker_count,omitempty"` + BuyMakerNotional *string `json:"buy_maker_notional,omitempty"` + BuyTakerBase *string `json:"buy_taker_base,omitempty"` + BuyTakerCount *int `json:"buy_taker_count,omitempty"` + BuyTakerNotional *string `json:"buy_taker_notional,omitempty"` + DataDate *string `json:"data_date,omitempty"` + MakerBuySellRatio *string `json:"maker_buy_sell_ratio,omitempty"` + NotionalCurrency *string `json:"notional_currency,omitempty"` + QuoteCurrency *string `json:"quote_currency,omitempty"` + SellMakerBase *string `json:"sell_maker_base,omitempty"` + SellMakerCount *int `json:"sell_maker_count,omitempty"` + SellMakerNotional *string `json:"sell_maker_notional,omitempty"` + SellTakerBase *string `json:"sell_taker_base,omitempty"` + SellTakerCount *int `json:"sell_taker_count,omitempty"` + SellTakerNotional *string `json:"sell_taker_notional,omitempty"` + Symbol *string `json:"symbol,omitempty"` + TotalVolumeBase *string `json:"total_volume_base,omitempty"` +} + +// Transaction defines model for Transaction. +type Transaction struct { + union json.RawMessage +} + +// Transaction0 Trade Reponse +type Transaction0 struct { + // Account The account. + Account *string `json:"account,omitempty"` + + // Amount The quantity that was executed. + Amount *string `json:"amount,omitempty"` + + // ClientOrderId The client order ID, if defined. Otherwise an empty string. + ClientOrderId *string `json:"clientOrderId,omitempty"` + + // Exchange Will always be "gemini". + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeAssetCode The symbol that the trade was for + FeeAssetCode *string `json:"feeAssetCode,omitempty"` + + // IsAggressor If true, this order was the taker in the trade. + IsAggressor *bool `json:"isAggressor,omitempty"` + + // IsAuctionFill True if the trade was a auction trade and not an on-exchange trade. + IsAuctionFill *bool `json:"isAuctionFill,omitempty"` + + // IsClearingFill True if the trade was a clearing trade and not an on-exchange trade. + IsClearingFill *bool `json:"isClearingFill,omitempty"` + + // OrderId The order that this trade executed against. + OrderId *int64 `json:"orderId,omitempty"` + + // Price The price that the execution happened at. + Price *string `json:"price,omitempty"` + + // Side Indicating the side of the original order. + Side *string `json:"side,omitempty"` + + // Symbol The symbol that the trade was for. + Symbol *string `json:"symbol,omitempty"` + + // Tid The trade ID. + Tid *int64 `json:"tid,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` +} + +// Transaction1 Transfer Reponse +type Transaction1 struct { + // AdvanceEid Deposit advance event ID. + AdvanceEid *int64 `json:"advanceEid,omitempty"` + + // Amount The quantity that was transferred. + Amount *string `json:"amount,omitempty"` + + // BankId Bank ID. + BankId *string `json:"bankId,omitempty"` + + // ClientTransferId Client Transfer ID. Client transfer ID is an optional client-supplied unique identifier for each withdrawal or internal transfer. + ClientTransferId *string `json:"clientTransferId,omitempty"` + + // CorrelationId Correlation ID. + CorrelationId *int64 `json:"correlationId,omitempty"` + + // Currency Currency code, see symbols + Currency *string `json:"currency,omitempty"` + + // Destination The account you are transferring to. + Destination *string `json:"destination,omitempty"` + + // Eid Transfer event id. + Eid *int64 `json:"eid,omitempty"` + + // FeeId Fee ID. + FeeId *string `json:"feeId,omitempty"` + + // Method Type of transfer method. + Method *string `json:"method,omitempty"` + + // OperationReason The operation reason. + OperationReason *string `json:"operationReason,omitempty"` + + // PendingEid Pending event ID. + PendingEid *int64 `json:"pendingEid,omitempty"` + + // Purpose Purpose. + Purpose *string `json:"purpose,omitempty"` + + // Source The account you are transferring from. + Source *string `json:"source,omitempty"` + + // Status The status of the transfer. + Status *string `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TransactionHash Supplies the transaction hash when available. + TransactionHash *string `json:"transactionHash,omitempty"` + + // TransferId Transfer ID. + TransferId *string `json:"transferId,omitempty"` + + // TransferType Transfer type. + TransferType *string `json:"transferType,omitempty"` + + // WithdrawalEid Withdrawal event ID. + WithdrawalEid *int64 `json:"withdrawalEid,omitempty"` + + // WithdrawalId Withdrawal ID. + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// Transfer defines model for Transfer. +type Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Eid The transfer ID + Eid *int64 `json:"eid,omitempty"` + Status *TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The transaction hash if applicable + TxHash *string `json:"txHash,omitempty"` + Type *TransferType `json:"type,omitempty"` +} + +// TransferStatus defines model for Transfer.Status. +type TransferStatus string + +// TransferType defines model for Transfer.Type. +type TransferType string + +// V2Transfer defines model for V2Transfer. +type V2Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Destination The destination address for withdrawals + Destination *string `json:"destination,omitempty"` + + // Eid The transfer event ID + Eid *int64 `json:"eid,omitempty"` + + // FeeAmount The fee charged for the transfer + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency The currency in which the fee was charged + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // Method The transfer method (e.g., `ACH`, `CreditCard`) + Method *string `json:"method,omitempty"` + + // Network The blockchain network the transfer was executed on (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`). Not present for fiat or administrative transfers. + Network *string `json:"network,omitempty"` + + // OutputIdx The output index for withdrawals + OutputIdx *int `json:"outputIdx,omitempty"` + + // Purpose The purpose or reason for administrative transfers + Purpose *string `json:"purpose,omitempty"` + + // Status The status of the transfer + Status *V2TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The on-chain transaction hash, if applicable + TxHash *string `json:"txHash,omitempty"` + + // Type The type of the transfer + Type *V2TransferType `json:"type,omitempty"` + + // WithdrawalId The unique withdrawal identifier + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// V2TransferStatus The status of the transfer +type V2TransferStatus string + +// V2TransferType The type of the transfer +type V2TransferType string + +// WithdrawCryptoFundsResponse Response returned after submitting a v2 cryptocurrency withdrawal. +type WithdrawCryptoFundsResponse struct { + // Address Standard string format of the withdrawal destination address + Address *string `json:"address,omitempty"` + + // Amount The withdrawal amount + Amount *string `json:"amount,omitempty"` + + // Currency The currency code of the withdrawn asset + Currency *string `json:"currency,omitempty"` + + // Fee The fee charged for the withdrawal + Fee *string `json:"fee,omitempty"` + + // WithdrawalId A unique ID for the withdrawal + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// ApiKeyAuth defines model for apiKeyAuth. +type ApiKeyAuth = string + +// CacheControl defines model for cacheControl. +type CacheControl = string + +// ContentLength defines model for contentLength. +type ContentLength = string + +// ContentType defines model for contentType. +type ContentType = string + +// CurrencyParam defines model for currencyParam. +type CurrencyParam = string + +// NetworkParam defines model for networkParam. +type NetworkParam = string + +// PayloadAuth defines model for payloadAuth. +type PayloadAuth = string + +// SignatureAuth defines model for signatureAuth. +type SignatureAuth = string + +// SymbolParam defines model for symbolParam. +type SymbolParam = string + +// TimestampParam timestamp +type TimestampParam = TimestampType + +// ApiKeyIpFilteringFailure defines model for ApiKeyIpFilteringFailure. +type ApiKeyIpFilteringFailure = ErrorResponse + +// BadRequest defines model for BadRequest. +type BadRequest = ErrorResponse + +// InternalError defines model for InternalError. +type InternalError = ErrorResponse + +// NotFound defines model for NotFound. +type NotFound = ErrorResponse + +// TooManyRequests defines model for TooManyRequests. +type TooManyRequests = ErrorResponse + +// Unauthorized defines model for Unauthorized. +type Unauthorized = ErrorResponse + +// apiKeyAuthContextKey is the context key for apiKeyAuth security scheme +type apiKeyAuthContextKey string + +// payloadAuthContextKey is the context key for payloadAuth security scheme +type payloadAuthContextKey string + +// signatureAuthContextKey is the context key for signatureAuth security scheme +type signatureAuthContextKey string + +// GetAccountDetailJSONBody defines parameters for GetAccountDetail. +type GetAccountDetailJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/account" + Request string `json:"request"` +} + +// GetAccountDetailParams defines parameters for GetAccountDetail. +type GetAccountDetailParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CreateNewAccountJSONBody defines parameters for CreateNewAccount. +type CreateNewAccountJSONBody struct { + // Name A unique name for the new account + Name string `json:"name"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/account/create" + Request string `json:"request"` + + // Type Either `exchange` or `custody` is accepted. Will generate an exchange account if `exchange` or parameter is missing. Will generate a custody account if `custody`. + Type *string `json:"type,omitempty"` +} + +// CreateNewAccountParams defines parameters for CreateNewAccount. +type CreateNewAccountParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListAccountsInGroupJSONBody defines parameters for ListAccountsInGroup. +type ListAccountsInGroupJSONBody struct { + // LimitAccounts The maximum number of accounts to return. Maximum and default values are both 500. + LimitAccounts *int `json:"limit_accounts,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/account/list" + Request string `json:"request"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ListAccountsInGroupParams defines parameters for ListAccountsInGroup. +type ListAccountsInGroupParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// RenameAccountJSONBody defines parameters for RenameAccount. +type RenameAccountJSONBody struct { + // Account Only required when using a master api-key. The shortname of the account within the subaccount group. Master API keys can get all account shortnames from the `account` field returned by the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + Account *string `json:"account,omitempty"` + + // NewAccount A unique shortname for the new account. If not provided, shortname will not change. + NewAccount *string `json:"newAccount,omitempty"` + + // NewName A unique name for the new account. If not provided, name will not change. + NewName *string `json:"newName,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/account/rename". + Request string `json:"request"` +} + +// RenameAccountParams defines parameters for RenameAccount. +type RenameAccountParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// TransferBetweenAccountsJSONBody defines parameters for TransferBetweenAccounts. +type TransferBetweenAccountsJSONBody struct { + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // ClientTransferId A unique identifier for the internal transfer, in uuid4 format + ClientTransferId *string `json:"clientTransferId,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v1/account/transfer/:currency` where `:currency` is replaced with either `usd` or a supported crypto-currency, e.g. `gusd`, `btc`, `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums). + Request string `json:"request"` + + // SourceAccount Nickname of the account you are transferring from. Use the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group) to get all account names in the group. + SourceAccount string `json:"sourceAccount"` + + // TargetAccount Nickname of the account you are transferring to. Use the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group) to get all account names in the group. + TargetAccount string `json:"targetAccount"` + + // WithdrawalId Unique ID of the requested withdrawal. + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// TransferBetweenAccountsParams defines parameters for TransferBetweenAccounts. +type TransferBetweenAccountsParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListDepositAddressesJSONBody defines parameters for ListDepositAddresses. +type ListDepositAddressesJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/addresses/network" + Request string `json:"request"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ListDepositAddressesParams defines parameters for ListDepositAddresses. +type ListDepositAddressesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListApprovedAddressesJSONBody defines parameters for ListApprovedAddresses. +type ListApprovedAddressesJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to view the approved address list. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/approvedAddresses/account/:network" where `:network` can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Request string `json:"request"` +} + +// ListApprovedAddressesParams defines parameters for ListApprovedAddresses. +type ListApprovedAddressesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// RemoveApprovedAddressJSONBody defines parameters for RemoveApprovedAddress. +type RemoveApprovedAddressJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to remove the approved address. + Account *string `json:"account,omitempty"` + + // Address A string of the address to be removed from the approved address list. + Address string `json:"address"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/approvedAddresses/:network/remove" where `:network` can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Request string `json:"request"` +} + +// RemoveApprovedAddressParams defines parameters for RemoveApprovedAddress. +type RemoveApprovedAddressParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CreateNewApprovedAddressJSONBody defines parameters for CreateNewApprovedAddress. +type CreateNewApprovedAddressJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to add the approved address. + Account *string `json:"account,omitempty"` + + // Address A string of the address to be added to the approved address list. + Address string `json:"address"` + + // Label The label of the approved address. + Label string `json:"label"` + + // Memo it would be present if applicable, it will be present for cosmos address. + Memo *string `json:"memo,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/approvedAddresses/:network/request" where `:network` can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Request string `json:"request"` +} + +// CreateNewApprovedAddressParams defines parameters for CreateNewApprovedAddress. +type CreateNewApprovedAddressParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetAvailableBalancesJSONBody defines parameters for GetAvailableBalances. +type GetAvailableBalancesJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account string `json:"account"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // ShowPendingBalances Whether to include pending balances such as in-flight crypto deposits or withdrawals in the balances response. + // + // > **Note:** Setting this field to `true` will result in slower response times due to additional database lookups required to retrieve pending balance information. + ShowPendingBalances *bool `json:"showPendingBalances,omitempty"` +} + +// GetAvailableBalancesParams defines parameters for GetAvailableBalances. +type GetAvailableBalancesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListStakingBalancesJSONBody defines parameters for ListStakingBalances. +type ListStakingBalancesJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/balances/staking" + Request string `json:"request"` +} + +// ListStakingBalancesParams defines parameters for ListStakingBalances. +type ListStakingBalancesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListCustodyFeeTransfersJSONBody defines parameters for ListCustodyFeeTransfers. +type ListCustodyFeeTransfersJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // LimitTransfers The maximum number of Custody fee records to return. The default is 10 and the maximum is 50. + LimitTransfers *int `json:"limit_transfers,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/custodyaccountfees" + Request string `json:"request"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ListCustodyFeeTransfersParams defines parameters for ListCustodyFeeTransfers. +type ListCustodyFeeTransfersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CreateNewDepositAddressJSONBody defines parameters for CreateNewDepositAddress. +type CreateNewDepositAddressJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Label A label for the address + Label *string `json:"label,omitempty"` + + // Legacy Whether to generate a legacy P2SH-P2PKH litecoin address. False by default. + Legacy *bool `json:"legacy,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/deposit/network/newAddress" + Request string `json:"request"` +} + +// CreateNewDepositAddressParams defines parameters for CreateNewDepositAddress. +type CreateNewDepositAddressParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetNotionalBalancesJSONBody defines parameters for GetNotionalBalances. +type GetNotionalBalancesJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/notionalbalances/currency" + Request string `json:"request"` +} + +// GetNotionalBalancesParams defines parameters for GetNotionalBalances. +type GetNotionalBalancesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// RevokeOAuthTokenJSONBody defines parameters for RevokeOAuthToken. +type RevokeOAuthTokenJSONBody struct { + // Request The literal string "/v1/oauth/revokeByToken" + Request string `json:"request"` +} + +// RevokeOAuthTokenParams defines parameters for RevokeOAuthToken. +type RevokeOAuthTokenParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// AddBankJSONBody defines parameters for AddBank. +type AddBankJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + Account *string `json:"account,omitempty"` + + // Accountnumber Account number of bank account to be added + Accountnumber string `json:"accountnumber"` + + // Name The name of the bank account as shown on your account statements + Name string `json:"name"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/payments/addbank" + Request string `json:"request"` + + // Routing Routing number of bank account to be added + Routing string `json:"routing"` + + // Type Type of bank account to be added. Accepts `checking` or `savings` + Type AddBankJSONBodyType `json:"type"` +} + +// AddBankParams defines parameters for AddBank. +type AddBankParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// AddBankJSONBodyType defines parameters for AddBank. +type AddBankJSONBodyType string + +// AddBankCADJSONBody defines parameters for AddBankCAD. +type AddBankCADJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + Account *string `json:"account,omitempty"` + + // AccountNumber Account number of bank account to be added + AccountNumber string `json:"accountNumber"` + + // Branchnnumber The branch number - optional but recommended. + Branchnnumber *string `json:"branchnnumber,omitempty"` + + // InstitutionNumber The institution number of the account - optional but recommended. + InstitutionNumber *string `json:"institutionNumber,omitempty"` + + // Name The name of the bank account as shown on your account statements + Name string `json:"name"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/payments/addbank/cad" + Request string `json:"request"` + + // Swiftcode The account SWIFT code + Swiftcode string `json:"swiftcode"` + + // Type Type of bank account to be added. Accepts `checking` or `savings` + Type AddBankCADJSONBodyType `json:"type"` +} + +// AddBankCADParams defines parameters for AddBankCAD. +type AddBankCADParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// AddBankCADJSONBodyType defines parameters for AddBankCAD. +type AddBankCADJSONBodyType string + +// ListPaymentMethodsJSONBody defines parameters for ListPaymentMethods. +type ListPaymentMethodsJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Master API keys can get all account names using the [Get Accounts endpoint](/rest/account-administration#list-accounts-in-group). + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/payments/methods" + Request string `json:"request"` +} + +// ListPaymentMethodsParams defines parameters for ListPaymentMethods. +type ListPaymentMethodsParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetRolesJSONBody defines parameters for GetRoles. +type GetRolesJSONBody struct { + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/roles" + Request string `json:"request"` +} + +// GetRolesParams defines parameters for GetRoles. +type GetRolesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListStakingEventHistoryJSONBody defines parameters for ListStakingEventHistory. +type ListStakingEventHistoryJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // InterestOnly Toggles whether to only return daily interest transactions. Defaults to false. + InterestOnly *bool `json:"interestOnly,omitempty"` + + // Limit The maximum number of transactions to return. Default is 50, max is 500. + Limit *int `json:"limit,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // ProviderId Borrower Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response + ProviderId *string `json:"providerId,omitempty"` + + // Request The literal string "/v1/staking/history" + Request string `json:"request"` + + // Since In iso datetime with timezone format. Defaults to the timestamp of the first deposit into Staking. + Since *TimestampType `json:"since,omitempty"` + + // SortAsc Toggles whether to sort the transactions in ascending order by datetime. Defaults to false. + SortAsc *bool `json:"sortAsc,omitempty"` + + // Until In iso datetime with timezone format, default to current time as of server time + Until *TimestampType `json:"until,omitempty"` +} + +// ListStakingEventHistoryParams defines parameters for ListStakingEventHistory. +type ListStakingEventHistoryParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListStakingRewardsJSONBody defines parameters for ListStakingRewards. +type ListStakingRewardsJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // ProviderId Borrower Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response + ProviderId *string `json:"providerId,omitempty"` + + // Request The literal string "/v1/staking/rewards" + Request string `json:"request"` + + // Since In iso datetime with timezone format + Since string `json:"since"` + + // Until In iso datetime with timezone format, default to current time as of server time + Until *string `json:"until,omitempty"` +} + +// ListStakingRewardsParams defines parameters for ListStakingRewards. +type ListStakingRewardsParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// StakeCryptoFundsJSONBody defines parameters for StakeCryptoFunds. +type StakeCryptoFundsJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Amount The amount of currency to deposit + Amount string `json:"amount"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency string `json:"currency"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // ProviderId Provider Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response + ProviderId string `json:"providerId"` + + // Request The literal string "v1/staking/stake" + Request string `json:"request"` +} + +// StakeCryptoFundsParams defines parameters for StakeCryptoFunds. +type StakeCryptoFundsParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// UnstakeCryptoFundsJSONBody defines parameters for UnstakeCryptoFunds. +type UnstakeCryptoFundsJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Amount The amount of currency to withdraw + Amount string `json:"amount"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency string `json:"currency"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // ProviderId Provider Id, in uuid4 format. providerId is accessible from the [Staking rates](#list-staking-rates) response + ProviderId string `json:"providerId"` + + // Request The literal string "v1/staking/unstake" + Request string `json:"request"` +} + +// UnstakeCryptoFundsParams defines parameters for UnstakeCryptoFunds. +type UnstakeCryptoFundsParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetTransactionHistoryJSONBody defines parameters for GetTransactionHistory. +type GetTransactionHistoryJSONBody struct { + // ContinuationToken For subsequent requests, use the returned `continuation_token` value for next page. If this is defined, do not define “timestamp_nanos”. + ContinuationToken *string `json:"continuation_token,omitempty"` + + // Limit The maximum number of transfers to return. The default is 100 and the maximum is 300. + Limit *int `json:"limit,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/transactions" + Request string `json:"request"` + + // TimestampNanos Only return transfers on or after this timestamp in nanos. If this is defined, do not define “continuation_token”. + TimestampNanos *TimestampType `json:"timestamp_nanos,omitempty"` +} + +// GetTransactionHistoryParams defines parameters for GetTransactionHistory. +type GetTransactionHistoryParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListPastTransfersJSONBody defines parameters for ListPastTransfers. +type ListPastTransfersJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` + + // LimitTransfers The maximum number of transfers to return. The default is 10 and the maximum is 50. + LimitTransfers *int `json:"limit_transfers,omitempty"` + + // Network Filter transfers by blockchain network (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`) + Network *string `json:"network,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v2/transfers" + Request string `json:"request"` + + // ShowCompletedDepositAdvances Whether to display completed deposit advances. True by default. + ShowCompletedDepositAdvances *bool `json:"show_completed_deposit_advances,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ListPastTransfersParams defines parameters for ListPastTransfers. +type ListPastTransfersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// WithdrawCryptoFundsJSONBody defines parameters for WithdrawCryptoFunds. +type WithdrawCryptoFundsJSONBody struct { + // Address The destination address for the withdrawal + Address string `json:"address"` + + // Amount The amount to withdraw + Amount string `json:"amount"` + + // ClientTransferId A unique UUID for idempotent withdrawals. If provided, duplicate requests with the same `clientTransferId` will not create additional withdrawals. + ClientTransferId *openapi_types.UUID `json:"clientTransferId,omitempty"` + + // Memo Required for certain networks that use memos (e.g., Solana, XRP, Cosmos). The destination tag or memo for the withdrawal. + Memo *string `json:"memo,omitempty"` +} + +// WithdrawCryptoFundsParams defines parameters for WithdrawCryptoFunds. +type WithdrawCryptoFundsParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetGasFeeEstimationParams defines parameters for GetGasFeeEstimation. +type GetGasFeeEstimationParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetAccountDetailJSONRequestBody defines body for GetAccountDetail for application/json ContentType. +type GetAccountDetailJSONRequestBody GetAccountDetailJSONBody + +// CreateNewAccountJSONRequestBody defines body for CreateNewAccount for application/json ContentType. +type CreateNewAccountJSONRequestBody CreateNewAccountJSONBody + +// ListAccountsInGroupJSONRequestBody defines body for ListAccountsInGroup for application/json ContentType. +type ListAccountsInGroupJSONRequestBody ListAccountsInGroupJSONBody + +// RenameAccountJSONRequestBody defines body for RenameAccount for application/json ContentType. +type RenameAccountJSONRequestBody RenameAccountJSONBody + +// TransferBetweenAccountsJSONRequestBody defines body for TransferBetweenAccounts for application/json ContentType. +type TransferBetweenAccountsJSONRequestBody TransferBetweenAccountsJSONBody + +// ListDepositAddressesJSONRequestBody defines body for ListDepositAddresses for application/json ContentType. +type ListDepositAddressesJSONRequestBody ListDepositAddressesJSONBody + +// ListApprovedAddressesJSONRequestBody defines body for ListApprovedAddresses for application/json ContentType. +type ListApprovedAddressesJSONRequestBody ListApprovedAddressesJSONBody + +// RemoveApprovedAddressJSONRequestBody defines body for RemoveApprovedAddress for application/json ContentType. +type RemoveApprovedAddressJSONRequestBody RemoveApprovedAddressJSONBody + +// CreateNewApprovedAddressJSONRequestBody defines body for CreateNewApprovedAddress for application/json ContentType. +type CreateNewApprovedAddressJSONRequestBody CreateNewApprovedAddressJSONBody + +// GetAvailableBalancesJSONRequestBody defines body for GetAvailableBalances for application/json ContentType. +type GetAvailableBalancesJSONRequestBody GetAvailableBalancesJSONBody + +// ListStakingBalancesJSONRequestBody defines body for ListStakingBalances for application/json ContentType. +type ListStakingBalancesJSONRequestBody ListStakingBalancesJSONBody + +// ListCustodyFeeTransfersJSONRequestBody defines body for ListCustodyFeeTransfers for application/json ContentType. +type ListCustodyFeeTransfersJSONRequestBody ListCustodyFeeTransfersJSONBody + +// CreateNewDepositAddressJSONRequestBody defines body for CreateNewDepositAddress for application/json ContentType. +type CreateNewDepositAddressJSONRequestBody CreateNewDepositAddressJSONBody + +// GetNotionalBalancesJSONRequestBody defines body for GetNotionalBalances for application/json ContentType. +type GetNotionalBalancesJSONRequestBody GetNotionalBalancesJSONBody + +// RevokeOAuthTokenJSONRequestBody defines body for RevokeOAuthToken for application/json ContentType. +type RevokeOAuthTokenJSONRequestBody RevokeOAuthTokenJSONBody + +// AddBankJSONRequestBody defines body for AddBank for application/json ContentType. +type AddBankJSONRequestBody AddBankJSONBody + +// AddBankCADJSONRequestBody defines body for AddBankCAD for application/json ContentType. +type AddBankCADJSONRequestBody AddBankCADJSONBody + +// ListPaymentMethodsJSONRequestBody defines body for ListPaymentMethods for application/json ContentType. +type ListPaymentMethodsJSONRequestBody ListPaymentMethodsJSONBody + +// GetRolesJSONRequestBody defines body for GetRoles for application/json ContentType. +type GetRolesJSONRequestBody GetRolesJSONBody + +// ListStakingEventHistoryJSONRequestBody defines body for ListStakingEventHistory for application/json ContentType. +type ListStakingEventHistoryJSONRequestBody ListStakingEventHistoryJSONBody + +// ListStakingRewardsJSONRequestBody defines body for ListStakingRewards for application/json ContentType. +type ListStakingRewardsJSONRequestBody ListStakingRewardsJSONBody + +// StakeCryptoFundsJSONRequestBody defines body for StakeCryptoFunds for application/json ContentType. +type StakeCryptoFundsJSONRequestBody StakeCryptoFundsJSONBody + +// UnstakeCryptoFundsJSONRequestBody defines body for UnstakeCryptoFunds for application/json ContentType. +type UnstakeCryptoFundsJSONRequestBody UnstakeCryptoFundsJSONBody + +// GetTransactionHistoryJSONRequestBody defines body for GetTransactionHistory for application/json ContentType. +type GetTransactionHistoryJSONRequestBody GetTransactionHistoryJSONBody + +// ListPastTransfersJSONRequestBody defines body for ListPastTransfers for application/json ContentType. +type ListPastTransfersJSONRequestBody ListPastTransfersJSONBody + +// WithdrawCryptoFundsJSONRequestBody defines body for WithdrawCryptoFunds for application/json ContentType. +type WithdrawCryptoFundsJSONRequestBody WithdrawCryptoFundsJSONBody + +// GetGasFeeEstimationJSONRequestBody defines body for GetGasFeeEstimation for application/json ContentType. +type GetGasFeeEstimationJSONRequestBody = FeeEstimateV2Request + +// AsHeartbeatNonce0 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce0 +func (t Heartbeat_Nonce) AsHeartbeatNonce0() (HeartbeatNonce0, error) { + var body HeartbeatNonce0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce0 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) FromHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce0 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsHeartbeatNonce1 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce1 +func (t Heartbeat_Nonce) AsHeartbeatNonce1() (HeartbeatNonce1, error) { + var body HeartbeatNonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce1 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) FromHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce1 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Heartbeat_Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Heartbeat_Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType returns the union data inside the Nonce as a TimestampType +func (t Nonce) AsTimestampType() (TimestampType, error) { + var body TimestampType + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType overwrites any union data inside the Nonce as the provided TimestampType +func (t *Nonce) FromTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType performs a merge with any union data inside the Nonce, using the provided TimestampType +func (t *Nonce) MergeTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNonce1 returns the union data inside the Nonce as a Nonce1 +func (t Nonce) AsNonce1() (Nonce1, error) { + var body Nonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNonce1 overwrites any union data inside the Nonce as the provided Nonce1 +func (t *Nonce) FromNonce1(v Nonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNonce1 performs a merge with any union data inside the Nonce, using the provided Nonce1 +func (t *Nonce) MergeNonce1(v Nonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType0 returns the union data inside the TimestampType as a TimestampType0 +func (t TimestampType) AsTimestampType0() (TimestampType0, error) { + var body TimestampType0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType0 overwrites any union data inside the TimestampType as the provided TimestampType0 +func (t *TimestampType) FromTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType0 performs a merge with any union data inside the TimestampType, using the provided TimestampType0 +func (t *TimestampType) MergeTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTimestampType1 returns the union data inside the TimestampType as a TimestampType1 +func (t TimestampType) AsTimestampType1() (TimestampType1, error) { + var body TimestampType1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType1 overwrites any union data inside the TimestampType as the provided TimestampType1 +func (t *TimestampType) FromTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType1 performs a merge with any union data inside the TimestampType, using the provided TimestampType1 +func (t *TimestampType) MergeTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t TimestampType) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *TimestampType) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTransaction0 returns the union data inside the Transaction as a Transaction0 +func (t Transaction) AsTransaction0() (Transaction0, error) { + var body Transaction0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction0 overwrites any union data inside the Transaction as the provided Transaction0 +func (t *Transaction) FromTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction0 performs a merge with any union data inside the Transaction, using the provided Transaction0 +func (t *Transaction) MergeTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTransaction1 returns the union data inside the Transaction as a Transaction1 +func (t Transaction) AsTransaction1() (Transaction1, error) { + var body Transaction1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction1 overwrites any union data inside the Transaction as the provided Transaction1 +func (t *Transaction) FromTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction1 performs a merge with any union data inside the Transaction, using the provided Transaction1 +func (t *Transaction) MergeTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Transaction) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Transaction) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/packages/sdk-go/generated/clearing/types.gen.go b/packages/sdk-go/generated/clearing/types.gen.go new file mode 100644 index 0000000..a5e6183 --- /dev/null +++ b/packages/sdk-go/generated/clearing/types.gen.go @@ -0,0 +1,3339 @@ +// Code generated from rest.yaml (Clearing, Instant). DO NOT EDIT. + +// Package clearing provides primitives to interact with the openapi HTTP API. +// +// Code generated by oapi-codegen. DO NOT EDIT. +package clearing + +import ( + "encoding/json" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/internal/runtime" + openapi_types "github.com/gemini/developer-platform/packages/sdk-go/types" +) + +const ( + ApiKeyAuthScopes apiKeyAuthContextKey = "apiKeyAuth.Scopes" + PayloadAuthScopes payloadAuthContextKey = "payloadAuth.Scopes" + SignatureAuthScopes signatureAuthContextKey = "signatureAuth.Scopes" +) + +// Defines values for BalanceType. +const ( + Exchange BalanceType = "exchange" +) + +// Valid indicates whether the value is a known member of the BalanceType enum. +func (e BalanceType) Valid() bool { + switch e { + case Exchange: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseReason. +const ( + ExceedsPriceLimits CancelOrderResponseReason = "ExceedsPriceLimits" + FillOrKillWouldNotFill CancelOrderResponseReason = "FillOrKillWouldNotFill" + ImmediateOrCancelWouldPost CancelOrderResponseReason = "ImmediateOrCancelWouldPost" + MakerOrCancelWouldTake CancelOrderResponseReason = "MakerOrCancelWouldTake" + MarketClosed CancelOrderResponseReason = "MarketClosed" + Requested CancelOrderResponseReason = "Requested" + SelfCrossPrevented CancelOrderResponseReason = "SelfCrossPrevented" + TradingClosed CancelOrderResponseReason = "TradingClosed" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseReason enum. +func (e CancelOrderResponseReason) Valid() bool { + switch e { + case ExceedsPriceLimits: + return true + case FillOrKillWouldNotFill: + return true + case ImmediateOrCancelWouldPost: + return true + case MakerOrCancelWouldTake: + return true + case MarketClosed: + return true + case Requested: + return true + case SelfCrossPrevented: + return true + case TradingClosed: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseSide. +const ( + CancelOrderResponseSideBuy CancelOrderResponseSide = "buy" + CancelOrderResponseSideSell CancelOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseSide enum. +func (e CancelOrderResponseSide) Valid() bool { + switch e { + case CancelOrderResponseSideBuy: + return true + case CancelOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseType. +const ( + CancelOrderResponseTypeExchangeLimit CancelOrderResponseType = "exchange limit" + CancelOrderResponseTypeExchangeMarket CancelOrderResponseType = "exchange market" + CancelOrderResponseTypeExchangeStopLimit CancelOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseType enum. +func (e CancelOrderResponseType) Valid() bool { + switch e { + case CancelOrderResponseTypeExchangeLimit: + return true + case CancelOrderResponseTypeExchangeMarket: + return true + case CancelOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for ClearingOrderSide. +const ( + ClearingOrderSideBuy ClearingOrderSide = "buy" + ClearingOrderSideSell ClearingOrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the ClearingOrderSide enum. +func (e ClearingOrderSide) Valid() bool { + switch e { + case ClearingOrderSideBuy: + return true + case ClearingOrderSideSell: + return true + default: + return false + } +} + +// Defines values for FundingPaymentEventType. +const ( + FundingPaymentEventTypeHourlyFundingTransfer FundingPaymentEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentEventType enum. +func (e FundingPaymentEventType) Valid() bool { + switch e { + case FundingPaymentEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemAction. +const ( + FundingPaymentReportItemActionCredit FundingPaymentReportItemAction = "Credit" + FundingPaymentReportItemActionDebit FundingPaymentReportItemAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemAction enum. +func (e FundingPaymentReportItemAction) Valid() bool { + switch e { + case FundingPaymentReportItemActionCredit: + return true + case FundingPaymentReportItemActionDebit: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemEventType. +const ( + FundingPaymentReportItemEventTypeHourlyFundingTransfer FundingPaymentReportItemEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemEventType enum. +func (e FundingPaymentReportItemEventType) Valid() bool { + switch e { + case FundingPaymentReportItemEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingTransferAction. +const ( + FundingTransferActionCredit FundingTransferAction = "Credit" + FundingTransferActionDebit FundingTransferAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingTransferAction enum. +func (e FundingTransferAction) Valid() bool { + switch e { + case FundingTransferActionCredit: + return true + case FundingTransferActionDebit: + return true + default: + return false + } +} + +// Defines values for InstantQuoteSide. +const ( + InstantQuoteSideBuy InstantQuoteSide = "buy" + InstantQuoteSideSell InstantQuoteSide = "sell" +) + +// Valid indicates whether the value is a known member of the InstantQuoteSide enum. +func (e InstantQuoteSide) Valid() bool { + switch e { + case InstantQuoteSideBuy: + return true + case InstantQuoteSideSell: + return true + default: + return false + } +} + +// Defines values for InterestRateInfoInterval. +const ( + Hour InterestRateInfoInterval = "hour" +) + +// Valid indicates whether the value is a known member of the InterestRateInfoInterval enum. +func (e InterestRateInfoInterval) Valid() bool { + switch e { + case Hour: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseSide. +const ( + LimitOrderResponseSideBuy LimitOrderResponseSide = "buy" + LimitOrderResponseSideSell LimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseSide enum. +func (e LimitOrderResponseSide) Valid() bool { + switch e { + case LimitOrderResponseSideBuy: + return true + case LimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseType. +const ( + LimitOrderResponseTypeExchangeLimit LimitOrderResponseType = "exchange limit" + LimitOrderResponseTypeExchangeMarket LimitOrderResponseType = "exchange market" + LimitOrderResponseTypeExchangeStopLimit LimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseType enum. +func (e LimitOrderResponseType) Valid() bool { + switch e { + case LimitOrderResponseTypeExchangeLimit: + return true + case LimitOrderResponseTypeExchangeMarket: + return true + case LimitOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for MyTradeBreak. +const ( + Empty MyTradeBreak = "" + TradeCorrect MyTradeBreak = "trade correct" +) + +// Valid indicates whether the value is a known member of the MyTradeBreak enum. +func (e MyTradeBreak) Valid() bool { + switch e { + case Empty: + return true + case TradeCorrect: + return true + default: + return false + } +} + +// Defines values for MyTradeType. +const ( + MyTradeTypeBuy MyTradeType = "Buy" + MyTradeTypeSell MyTradeType = "Sell" +) + +// Valid indicates whether the value is a known member of the MyTradeType enum. +func (e MyTradeType) Valid() bool { + switch e { + case MyTradeTypeBuy: + return true + case MyTradeTypeSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestOptions. +const ( + FillOrKill NewOrderRequestOptions = "fill-or-kill" + ImmediateOrCancel NewOrderRequestOptions = "immediate-or-cancel" + MakerOrCancel NewOrderRequestOptions = "maker-or-cancel" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestOptions enum. +func (e NewOrderRequestOptions) Valid() bool { + switch e { + case FillOrKill: + return true + case ImmediateOrCancel: + return true + case MakerOrCancel: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestSide. +const ( + NewOrderRequestSideBuy NewOrderRequestSide = "buy" + NewOrderRequestSideSell NewOrderRequestSide = "sell" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestSide enum. +func (e NewOrderRequestSide) Valid() bool { + switch e { + case NewOrderRequestSideBuy: + return true + case NewOrderRequestSideSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestType. +const ( + NewOrderRequestTypeExchangeLimit NewOrderRequestType = "exchange limit" + NewOrderRequestTypeExchangeMarket NewOrderRequestType = "exchange market" + NewOrderRequestTypeExchangeStopLimit NewOrderRequestType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestType enum. +func (e NewOrderRequestType) Valid() bool { + switch e { + case NewOrderRequestTypeExchangeLimit: + return true + case NewOrderRequestTypeExchangeMarket: + return true + case NewOrderRequestTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for OrderSide. +const ( + OrderSideBuy OrderSide = "buy" + OrderSideSell OrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the OrderSide enum. +func (e OrderSide) Valid() bool { + switch e { + case OrderSideBuy: + return true + case OrderSideSell: + return true + default: + return false + } +} + +// Defines values for OrderTradesType. +const ( + OrderTradesTypeBuy OrderTradesType = "Buy" + OrderTradesTypeSell OrderTradesType = "Sell" +) + +// Valid indicates whether the value is a known member of the OrderTradesType enum. +func (e OrderTradesType) Valid() bool { + switch e { + case OrderTradesTypeBuy: + return true + case OrderTradesTypeSell: + return true + default: + return false + } +} + +// Defines values for OrderType. +const ( + OrderTypeExchangeLimit OrderType = "exchange limit" + OrderTypeExchangeMarket OrderType = "exchange market" + OrderTypeExchangeStopLimit OrderType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the OrderType enum. +func (e OrderType) Valid() bool { + switch e { + case OrderTypeExchangeLimit: + return true + case OrderTypeExchangeMarket: + return true + case OrderTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for RiskStatsResponseProductType. +const ( + PerpetualSwapContract RiskStatsResponseProductType = "PerpetualSwapContract" +) + +// Valid indicates whether the value is a known member of the RiskStatsResponseProductType enum. +func (e RiskStatsResponseProductType) Valid() bool { + switch e { + case PerpetualSwapContract: + return true + default: + return false + } +} + +// Defines values for StakingTransactionTransactionType. +const ( + StakingTransactionTransactionTypeAdminCreditAdjustment StakingTransactionTransactionType = "AdminCreditAdjustment" + StakingTransactionTransactionTypeAdminDebitAdjustment StakingTransactionTransactionType = "AdminDebitAdjustment" + StakingTransactionTransactionTypeAdminRedeem StakingTransactionTransactionType = "AdminRedeem" + StakingTransactionTransactionTypeDeposit StakingTransactionTransactionType = "Deposit" + StakingTransactionTransactionTypeInterest StakingTransactionTransactionType = "Interest" + StakingTransactionTransactionTypeRedeem StakingTransactionTransactionType = "Redeem" + StakingTransactionTransactionTypeRedeemPayment StakingTransactionTransactionType = "RedeemPayment" +) + +// Valid indicates whether the value is a known member of the StakingTransactionTransactionType enum. +func (e StakingTransactionTransactionType) Valid() bool { + switch e { + case StakingTransactionTransactionTypeAdminCreditAdjustment: + return true + case StakingTransactionTransactionTypeAdminDebitAdjustment: + return true + case StakingTransactionTransactionTypeAdminRedeem: + return true + case StakingTransactionTransactionTypeDeposit: + return true + case StakingTransactionTransactionTypeInterest: + return true + case StakingTransactionTransactionTypeRedeem: + return true + case StakingTransactionTransactionTypeRedeemPayment: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseSide. +const ( + StopLimitOrderResponseSideBuy StopLimitOrderResponseSide = "buy" + StopLimitOrderResponseSideSell StopLimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseSide enum. +func (e StopLimitOrderResponseSide) Valid() bool { + switch e { + case StopLimitOrderResponseSideBuy: + return true + case StopLimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseType. +const ( + ExchangeStopLimit StopLimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseType enum. +func (e StopLimitOrderResponseType) Valid() bool { + switch e { + case ExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for TradeType. +const ( + TradeTypeBuy TradeType = "buy" + TradeTypeSell TradeType = "sell" +) + +// Valid indicates whether the value is a known member of the TradeType enum. +func (e TradeType) Valid() bool { + switch e { + case TradeTypeBuy: + return true + case TradeTypeSell: + return true + default: + return false + } +} + +// Defines values for TransferStatus. +const ( + TransferStatusComplete TransferStatus = "Complete" + TransferStatusPending TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the TransferStatus enum. +func (e TransferStatus) Valid() bool { + switch e { + case TransferStatusComplete: + return true + case TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for TransferType. +const ( + TransferTypeDeposit TransferType = "Deposit" + TransferTypeWithdrawal TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the TransferType enum. +func (e TransferType) Valid() bool { + switch e { + case TransferTypeDeposit: + return true + case TransferTypeWithdrawal: + return true + default: + return false + } +} + +// Defines values for V2TransferStatus. +const ( + V2TransferStatusAdvanced V2TransferStatus = "Advanced" + V2TransferStatusComplete V2TransferStatus = "Complete" + V2TransferStatusPending V2TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the V2TransferStatus enum. +func (e V2TransferStatus) Valid() bool { + switch e { + case V2TransferStatusAdvanced: + return true + case V2TransferStatusComplete: + return true + case V2TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for V2TransferType. +const ( + AdminCredit V2TransferType = "AdminCredit" + AdminDebit V2TransferType = "AdminDebit" + Deposit V2TransferType = "Deposit" + Reward V2TransferType = "Reward" + Withdrawal V2TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the V2TransferType enum. +func (e V2TransferType) Valid() bool { + switch e { + case AdminCredit: + return true + case AdminDebit: + return true + case Deposit: + return true + case Reward: + return true + case Withdrawal: + return true + default: + return false + } +} + +// Defines values for ListClearingBrokers200JSONResponseBodyOrdersSourceSide. +const ( + ListClearingBrokers200JSONResponseBodyOrdersSourceSideBuy ListClearingBrokers200JSONResponseBodyOrdersSourceSide = "buy" + ListClearingBrokers200JSONResponseBodyOrdersSourceSideSell ListClearingBrokers200JSONResponseBodyOrdersSourceSide = "sell" +) + +// Valid indicates whether the value is a known member of the ListClearingBrokers200JSONResponseBodyOrdersSourceSide enum. +func (e ListClearingBrokers200JSONResponseBodyOrdersSourceSide) Valid() bool { + switch e { + case ListClearingBrokers200JSONResponseBodyOrdersSourceSideBuy: + return true + case ListClearingBrokers200JSONResponseBodyOrdersSourceSideSell: + return true + default: + return false + } +} + +// Defines values for CreateNewBrokerOrderJSONBodySide. +const ( + CreateNewBrokerOrderJSONBodySideBuy CreateNewBrokerOrderJSONBodySide = "buy" + CreateNewBrokerOrderJSONBodySideSell CreateNewBrokerOrderJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the CreateNewBrokerOrderJSONBodySide enum. +func (e CreateNewBrokerOrderJSONBodySide) Valid() bool { + switch e { + case CreateNewBrokerOrderJSONBodySideBuy: + return true + case CreateNewBrokerOrderJSONBodySideSell: + return true + default: + return false + } +} + +// Defines values for ConfirmClearingOrderJSONBodySide. +const ( + ConfirmClearingOrderJSONBodySideBuy ConfirmClearingOrderJSONBodySide = "buy" + ConfirmClearingOrderJSONBodySideSell ConfirmClearingOrderJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the ConfirmClearingOrderJSONBodySide enum. +func (e ConfirmClearingOrderJSONBodySide) Valid() bool { + switch e { + case ConfirmClearingOrderJSONBodySideBuy: + return true + case ConfirmClearingOrderJSONBodySideSell: + return true + default: + return false + } +} + +// Defines values for ListClearingOrdersJSONBodySide. +const ( + ListClearingOrdersJSONBodySideBuy ListClearingOrdersJSONBodySide = "buy" + ListClearingOrdersJSONBodySideSell ListClearingOrdersJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the ListClearingOrdersJSONBodySide enum. +func (e ListClearingOrdersJSONBodySide) Valid() bool { + switch e { + case ListClearingOrdersJSONBodySideBuy: + return true + case ListClearingOrdersJSONBodySideSell: + return true + default: + return false + } +} + +// Defines values for ListClearingOrders200JSONResponseBodyOrdersSide. +const ( + ListClearingOrders200JSONResponseBodyOrdersSideBuy ListClearingOrders200JSONResponseBodyOrdersSide = "buy" + ListClearingOrders200JSONResponseBodyOrdersSideSell ListClearingOrders200JSONResponseBodyOrdersSide = "sell" +) + +// Valid indicates whether the value is a known member of the ListClearingOrders200JSONResponseBodyOrdersSide enum. +func (e ListClearingOrders200JSONResponseBodyOrdersSide) Valid() bool { + switch e { + case ListClearingOrders200JSONResponseBodyOrdersSideBuy: + return true + case ListClearingOrders200JSONResponseBodyOrdersSideSell: + return true + default: + return false + } +} + +// Defines values for CreateNewClearingOrderJSONBodySide. +const ( + CreateNewClearingOrderJSONBodySideBuy CreateNewClearingOrderJSONBodySide = "buy" + CreateNewClearingOrderJSONBodySideSell CreateNewClearingOrderJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the CreateNewClearingOrderJSONBodySide enum. +func (e CreateNewClearingOrderJSONBodySide) Valid() bool { + switch e { + case CreateNewClearingOrderJSONBodySideBuy: + return true + case CreateNewClearingOrderJSONBodySideSell: + return true + default: + return false + } +} + +// Defines values for ListClearingTrades200JSONResponseBodyResultsSourceSide. +const ( + ListClearingTrades200JSONResponseBodyResultsSourceSideBuy ListClearingTrades200JSONResponseBodyResultsSourceSide = "buy" + ListClearingTrades200JSONResponseBodyResultsSourceSideSell ListClearingTrades200JSONResponseBodyResultsSourceSide = "sell" +) + +// Valid indicates whether the value is a known member of the ListClearingTrades200JSONResponseBodyResultsSourceSide enum. +func (e ListClearingTrades200JSONResponseBodyResultsSourceSide) Valid() bool { + switch e { + case ListClearingTrades200JSONResponseBodyResultsSourceSideBuy: + return true + case ListClearingTrades200JSONResponseBodyResultsSourceSideSell: + return true + default: + return false + } +} + +// Defines values for ExecuteInstantOrderJSONBodySide. +const ( + ExecuteInstantOrderJSONBodySideBuy ExecuteInstantOrderJSONBodySide = "buy" + ExecuteInstantOrderJSONBodySideSell ExecuteInstantOrderJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the ExecuteInstantOrderJSONBodySide enum. +func (e ExecuteInstantOrderJSONBodySide) Valid() bool { + switch e { + case ExecuteInstantOrderJSONBodySideBuy: + return true + case ExecuteInstantOrderJSONBodySideSell: + return true + default: + return false + } +} + +// Defines values for GetInstantQuoteJSONBodySide. +const ( + Buy GetInstantQuoteJSONBodySide = "buy" + Sell GetInstantQuoteJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the GetInstantQuoteJSONBodySide enum. +func (e GetInstantQuoteJSONBodySide) Valid() bool { + switch e { + case Buy: + return true + case Sell: + return true + default: + return false + } +} + +// Account defines model for Account. +type Account struct { + // AccountId The account ID + AccountId *string `json:"account_id,omitempty"` + + // Created The creation date + Created *string `json:"created,omitempty"` + + // IsDefault Whether the account is the default account + IsDefault *bool `json:"is_default,omitempty"` + + // Name The account name + Name *string `json:"name,omitempty"` +} + +// AddBankResponse defines model for AddBankResponse. +type AddBankResponse struct { + // ReferenceId Reference ID for the new bank addition request. Once received, send in a wire from the requested bank account to verify it and enable withdrawals to that account. + ReferenceId *string `json:"referenceId,omitempty"` + + // Result Status result (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// Address defines model for Address. +type Address struct { + // Address String representation of the cryptocurrency address + Address *string `json:"address,omitempty"` + + // Label If you provided a label when creating the address, it will be echoed back here + Label *string `json:"label,omitempty"` + + // Memo It would be present if applicable, it will be present for cosmos address + Memo *string `json:"memo,omitempty"` + + // Network The blockchain network for the address + Network *string `json:"network,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ApprovedAddress defines model for ApprovedAddress. +type ApprovedAddress struct { + // Address The address on the approved address list. + Address *string `json:"address,omitempty"` + + // CreatedAt UTC timestamp in millisecond of when the address was created. + CreatedAt *string `json:"createdAt,omitempty"` + + // Label The label assigned to the address + Label *string `json:"label,omitempty"` + + // Network The network of the approved address. Network can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Network *string `json:"network,omitempty"` + + // Scope Will return the scope of the address as either "account" or "group" + Scope *string `json:"scope,omitempty"` + + // Status The status of the address that will return as "active", "pending-time" or "pending-mua". The remaining time is exactly 7 days after the initial request. "pending-mua" is for multi-user accounts and will require another administator or fund manager on the account to approve the address. + Status *string `json:"status,omitempty"` +} + +// ApprovedAddressMessage defines model for ApprovedAddressMessage. +type ApprovedAddressMessage struct { + // Message Status or confirmation message for the approved address request or removal. + Message *string `json:"message,omitempty"` + + // Result Result status (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// ApprovedAddressesResponse Response envelope containing the approved withdrawal addresses. +type ApprovedAddressesResponse struct { + // ApprovedAddresses Array of approved addresses on both the account and group level. + ApprovedAddresses *[]ApprovedAddress `json:"approvedAddresses,omitempty"` +} + +// Balance defines model for Balance. +type Balance struct { + // UnderscoreTimestamp Server-side monotonically increasing clock value as an ISO 8601 timestamp. Clients can use this value to detect and filter out stale responses that may occur due to load balancing or potential stale servers. + UnderscoreTimestamp *time.Time `json:"_timestamp,omitempty"` + + // Amount The confirmed balance for the currency (also referred to as `confirmedBalance`). For crypto withdrawals, this value is **not** reduced until the withdrawal has been confirmed on the blockchain. This delay protects against blockchain reorganizations. Use the `available` field instead if you need balances that immediately reflect holds. + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Available The amount available for trading. This value is reduced **immediately** when an order hold or withdrawal hold is placed, making it the recommended field for tracking real-time spendable balances. + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The amount available for withdrawal + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Currency The currency symbol + Currency *string `json:"currency,omitempty"` + + // PendingDeposit The amount pending deposit + PendingDeposit *openapi_types.DecimalNumber `json:"pendingDeposit,omitempty"` + + // PendingWithdrawal The amount pending withdrawal + PendingWithdrawal *openapi_types.DecimalNumber `json:"pendingWithdrawal,omitempty"` + Type *BalanceType `json:"type,omitempty"` +} + +// BalanceType defines model for Balance.Type. +type BalanceType string + +// CancelAllOrdersBySessionRequest defines model for CancelAllOrdersBySessionRequest. +type CancelAllOrdersBySessionRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/session" + Request string `json:"request"` +} + +// CancelAllOrdersRequest defines model for CancelAllOrdersRequest. +type CancelAllOrdersRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/all" + Request string `json:"request"` +} + +// CancelAllResult defines model for CancelAllResult. +type CancelAllResult struct { + // Details cancelledOrders/cancelRejects with IDs of both + Details *struct { + CancelRejects *[]int64 `json:"cancelRejects,omitempty"` + CancelledOrders *[]int64 `json:"cancelledOrders,omitempty"` + } `json:"details,omitempty"` + Result *string `json:"result,omitempty"` +} + +// CancelOrderRequest defines model for CancelOrderRequest. +type CancelOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order ID given by `/order/new` + OrderId uint64 `json:"order_id"` + + // Request The literal string "/v1/order/cancel" + Request string `json:"request"` +} + +// CancelOrderResponse defines model for CancelOrderResponse. +type CancelOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Reason *CancelOrderResponseReason `json:"reason,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *CancelOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *CancelOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// CancelOrderResponseReason defines model for CancelOrderResponse.Reason. +type CancelOrderResponseReason string + +// CancelOrderResponseSide defines model for CancelOrderResponse.Side. +type CancelOrderResponseSide string + +// CancelOrderResponseType defines model for CancelOrderResponse.Type. +type CancelOrderResponseType string + +// Candle defines model for Candle. +type Candle = []float64 + +// CandleResponse defines model for CandleResponse. +type CandleResponse = []Candle + +// ClearingOrder defines model for ClearingOrder. +type ClearingOrder struct { + // Amount The order amount + Amount *string `json:"amount,omitempty"` + + // ClearingId The clearing ID + ClearingId *string `json:"clearing_id,omitempty"` + + // IsConfirmed Whether the order is confirmed + IsConfirmed *bool `json:"is_confirmed,omitempty"` + + // Price The order price + Price *string `json:"price,omitempty"` + Side *ClearingOrderSide `json:"side,omitempty"` + + // Status The order status + Status *string `json:"status,omitempty"` + + // Symbol The trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms The timestamp in milliseconds + Timestampms *int64 `json:"timestampms,omitempty"` +} + +// ClearingOrderSide defines model for ClearingOrder.Side. +type ClearingOrderSide string + +// CustodyFeeTransfer defines model for CustodyFeeTransfer. +type CustodyFeeTransfer struct { + // Eid Custody fee event id + Eid *int64 `json:"eid,omitempty"` + + // EventType Custody fee event type + EventType *string `json:"eventType,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // TxTime Time of Custody fee record in milliseconds + TxTime *int64 `json:"txTime,omitempty"` +} + +// ErrorResponse defines model for ErrorResponse. +type ErrorResponse struct { + // Message Detailed error message + Message *string `json:"message,omitempty"` + + // Reason A short description + Reason *string `json:"reason,omitempty"` + + // Result Error + Result *string `json:"result,omitempty"` +} + +// FeeEstimateRequest defines model for FeeEstimateRequest. +type FeeEstimateRequest struct { + // Account The name of the account within the subaccount group. + Account string `json:"account"` + + // Address Standard string format of cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v1/withdraw/{currencyCodeLowerCase}/feeEstimate` where `:currencyCodeLowerCase` is replaced with the currency code of a supported crypto-currency, e.g. `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateResponse defines model for FeeEstimateResponse. +type FeeEstimateResponse struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated gas fee + Fee *string `json:"fee,omitempty"` + + // IsOverride Value that shows if an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total nunber of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals left to use + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeeEstimateV2Request defines model for FeeEstimateV2Request. +type FeeEstimateV2Request struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Address Standard string format of the destination cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Memo It would be present if applicable, it will be present for cosmos address. + Memo *string `json:"memo,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v2/withdraw/{network}/{ticker}/feeEstimate` where `{network}` is the blockchain network (e.g. `ethereum`, `bitcoin`, `solana`) and `{ticker}` is the currency code (e.g. `eth`, `btc`, `sol`). See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateV2Response defines model for FeeEstimateV2Response. +type FeeEstimateV2Response struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated withdrawal fee as a decimal amount + Fee *openapi_types.DecimalNumber `json:"fee,omitempty"` + + // IsOverride Whether an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total number of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals remaining + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeePromos defines model for FeePromos. +type FeePromos struct { + // Symbols Symbols that currently have fee promos + Symbols *[]string `json:"symbols,omitempty"` +} + +// FundingAmountResponse defines model for FundingAmountResponse. +type FundingAmountResponse struct { + // Amount The dollar amount for a Long 1 position held in the symbol for funding period (1 hour) + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // EstimatedFundingAmount The estimated dollar amount for a Long 1 position held in the symbol for next funding period (1 hour) + EstimatedFundingAmount *openapi_types.DecimalNumber `json:"estimatedFundingAmount,omitempty"` + + // FundingDateTime UTC date time in format `yyyy-MM-ddThh:mm:ss.SSSZ` format + FundingDateTime *string `json:"fundingDateTime,omitempty"` + + // FundingTimestampMilliSecs Current funding amount Epoc time. + FundingTimestampMilliSecs *int64 `json:"fundingTimestampMilliSecs,omitempty"` + + // NextFundingTimestamp Next funding amount Epoc time. + NextFundingTimestamp *int64 `json:"nextFundingTimestamp,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` +} + +// FundingPayment defines model for FundingPayment. +type FundingPayment struct { + // EventType Event type + EventType FundingPaymentEventType `json:"eventType"` + HourlyFundingTransfer FundingTransfer `json:"hourlyFundingTransfer"` +} + +// FundingPaymentEventType Event type +type FundingPaymentEventType string + +// FundingPaymentReportItem defines model for FundingPaymentReportItem. +type FundingPaymentReportItem struct { + // Action Credit or Debit + Action FundingPaymentReportItemAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType FundingPaymentReportItemEventType `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingPaymentReportItemAction Credit or Debit +type FundingPaymentReportItemAction string + +// FundingPaymentReportItemEventType Event type +type FundingPaymentReportItemEventType string + +// FundingTransfer defines model for FundingTransfer. +type FundingTransfer struct { + // Action Credit or Debit + Action FundingTransferAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType string `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingTransferAction Credit or Debit +type FundingTransferAction string + +// FxRate defines model for FxRate. +type FxRate struct { + // AsOf timestamp + AsOf *TimestampType `json:"asOf,omitempty"` + + // Benchmark The market for which the retrieved price applies to + Benchmark *string `json:"benchmark,omitempty"` + + // FxPair The requested currency pair + FxPair *string `json:"fxPair,omitempty"` + + // Provider The market data provider + Provider *string `json:"provider,omitempty"` + + // Rate The exchange rate + Rate *float64 `json:"rate,omitempty"` +} + +// Heartbeat defines model for Heartbeat. +type Heartbeat struct { + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce *Heartbeat_Nonce `json:"nonce,omitempty"` + + // Request The literal string `/v1/heartbeat` + Request *string `json:"request,omitempty"` +} + +// HeartbeatNonce0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `'1495127793'` | `POST` only | +// | string (milliseconds) | `'1495127793000'` | `POST` only | +type HeartbeatNonce0 = string + +// HeartbeatNonce1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type HeartbeatNonce1 = int64 + +// Heartbeat_Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Heartbeat_Nonce struct { + union json.RawMessage +} + +// InstantQuote defines model for InstantQuote. +type InstantQuote struct { + // DepositFee The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + DepositFee *string `json:"depositFee,omitempty"` + + // DepositFeeCurrency Currency in which `depositFee` is taken + DepositFeeCurrency *string `json:"depositFeeCurrency,omitempty"` + + // Fee The fee quantity to be taken for the order upon execution + Fee *string `json:"fee,omitempty"` + + // FeeCurrency The currency label for the order + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // MaxAgeMs Number of milliseconds until this quote price expires. Once expired, you will need to request a new quote + MaxAgeMs *int `json:"maxAgeMs,omitempty"` + + // Pair The symbol passed in the quote request + Pair *string `json:"pair,omitempty"` + + // Price The quoted price of the asset. This will not change when attempting execution + Price *string `json:"price,omitempty"` + + // PriceCurrency The currency in which the order is priced. Matches `CCY2` in the symbol + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // Quantity The quantity of the asset to be bought or sold + Quantity *string `json:"quantity,omitempty"` + + // QuantityCurrency The currency label for the `quantity` field. Matches `CCY1` in the symbol + QuantityCurrency *string `json:"quantityCurrency,omitempty"` + + // QuoteId Unique ID for the quote. This is used in the execution of the order + QuoteId *int64 `json:"quoteId,omitempty"` + + // Side Either "buy" or "sell" + Side *InstantQuoteSide `json:"side,omitempty"` + + // TotalSpend Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + TotalSpend *string `json:"totalSpend,omitempty"` + + // TotalSpendCurrency Currency of the `totalSpend` to be spent on the order + TotalSpendCurrency *string `json:"totalSpendCurrency,omitempty"` +} + +// InstantQuoteSide Either "buy" or "sell" +type InstantQuoteSide string + +// InterestRateInfo defines model for InterestRateInfo. +type InterestRateInfo struct { + // Interval The time interval for the rate (currently only "hour" is supported) + Interval InterestRateInfoInterval `json:"interval"` + + // Rate The interest rate as a decimal string + Rate string `json:"rate"` +} + +// InterestRateInfoInterval The time interval for the rate (currently only "hour" is supported) +type InterestRateInfoInterval string + +// LimitOrderResponse defines model for LimitOrderResponse. +type LimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *LimitOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *LimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// LimitOrderResponseSide defines model for LimitOrderResponse.Side. +type LimitOrderResponseSide string + +// LimitOrderResponseType defines model for LimitOrderResponse.Type. +type LimitOrderResponseType string + +// LiquidationRisk defines model for LiquidationRisk. +type LiquidationRisk struct { + // LiquidationPrice The estimated price at which liquidation would occur (optional, may not be present for all positions) + LiquidationPrice *MoneyAmount `json:"liquidationPrice,omitempty"` + + // LossPercentage The percentage loss from current value that would trigger liquidation, formatted as decimal (e.g., "0.1550" = 15.50%) + LossPercentage string `json:"lossPercentage"` +} + +// MarginAccountSummary defines model for MarginAccountSummary. +type MarginAccountSummary struct { + // AvailableCollateral The amount of collateral available for new positions or withdrawals + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased with available collateral + BuyingPower MoneyAmount `json:"buyingPower"` + + // InterestRate Current interest rate on borrowed amounts (only present if borrows exist) + InterestRate *InterestRateInfo `json:"interestRate,omitempty"` + + // Leverage The current leverage ratio (notionalValue / marginAssetValue) + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if positions exist) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account that can contribute to funding positions + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold with available collateral + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed across all currencies + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MarginInterestRate defines model for MarginInterestRate. +type MarginInterestRate struct { + // BorrowRate The hourly borrow rate as a decimal + BorrowRate string `json:"borrowRate"` + + // BorrowRateAnnual The annualized borrow rate (daily rate × 365) + BorrowRateAnnual string `json:"borrowRateAnnual"` + + // BorrowRateDaily The daily borrow rate (hourly rate × 24) + BorrowRateDaily string `json:"borrowRateDaily"` + + // Currency The currency code (e.g., "BTC", "ETH", "USD") + Currency string `json:"currency"` + + // LastUpdated Unix timestamp in milliseconds when the rate was last updated + LastUpdated int64 `json:"lastUpdated"` +} + +// MarginOrderPreview defines model for MarginOrderPreview. +type MarginOrderPreview struct { + // Postorder Margin risk statistics after the order would be executed + Postorder MarginRiskStats `json:"postorder"` + + // Preorder Margin risk statistics before the order would be executed + Preorder MarginRiskStats `json:"preorder"` +} + +// MarginRatesResponse defines model for MarginRatesResponse. +type MarginRatesResponse struct { + // Rates Array of interest rates for all borrowable currencies + Rates []MarginInterestRate `json:"rates"` +} + +// MarginResponse defines model for MarginResponse. +type MarginResponse struct { + // AvailableMargin The difference between the `margin_assets_value` and `initial_margin`. + AvailableMargin *string `json:"available_margin,omitempty"` + + // BuyingPower The amount of that product the account could purchase based on current `initial_margin` and `margin_assets_value`. + BuyingPower *string `json:"buying_power,omitempty"` + + // EstimatedLiquidationPrice The estimated price for the asset at which liquidation would occur. + EstimatedLiquidationPrice *string `json:"estimated_liquidation_price,omitempty"` + + // InitialMargin The $ amount that is being required by the accounts current positions and open orders. + InitialMargin *string `json:"initial_margin,omitempty"` + + // InitialMarginPositions The contribution to `initial_margin` from open positions. + InitialMarginPositions *string `json:"initial_margin_positions,omitempty"` + + // Leverage The ratio of Notional Value to Margin Assets Value. + Leverage *string `json:"leverage,omitempty"` + + // MarginAssetsValue The $ equivalent value of all the assets available in the current trading account that can contribute to funding a derivatives position. + MarginAssetsValue *string `json:"margin_assets_value,omitempty"` + + // MarginMaintenanceLimit The minimum amount of `margin_assets_value` required before the account is moved to liquidation status. + MarginMaintenanceLimit *string `json:"margin_maintenance_limit,omitempty"` + + // NotionalValue The $ value of the current position. + NotionalValue *string `json:"notional_value,omitempty"` + + // ReservedMargin The contribution to `initial_margin` from open orders. + ReservedMargin *string `json:"reserved_margin,omitempty"` + + // ReservedMarginBuys The contribution to `initial_margin` from open BUY orders. + ReservedMarginBuys *string `json:"reserved_margin_buys,omitempty"` + + // ReservedMarginSells The contribution to `initial_margin` from open SELL orders. + ReservedMarginSells *string `json:"reserved_margin_sells,omitempty"` + + // SellingPower The amount of that product the account could sell based on current `initial_margin` and `margin_assets_value`. + SellingPower *string `json:"selling_power,omitempty"` +} + +// MarginRiskStats defines model for MarginRiskStats. +type MarginRiskStats struct { + // AvailableCollateral The amount of collateral available for new positions + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased + BuyingPower MoneyAmount `json:"buyingPower"` + + // Leverage The leverage ratio + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if applicable) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MoneyAmount defines model for MoneyAmount. +type MoneyAmount struct { + // Currency The currency code (e.g., "USD", "BTC", "ETH") + Currency string `json:"currency"` + + // Value The amount in the specified currency + Value string `json:"value"` +} + +// MyTrade defines model for MyTrade. +type MyTrade struct { + Aggressor *bool `json:"aggressor,omitempty"` + Amount *string `json:"amount,omitempty"` + Break *MyTradeBreak `json:"break,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + FeeAmount *string `json:"fee_amount,omitempty"` + FeeCurrency *string `json:"fee_currency,omitempty"` + IsAuctionFill *bool `json:"is_auction_fill,omitempty"` + OrderId *string `json:"order_id,omitempty"` + Price *string `json:"price,omitempty"` + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *MyTradeType `json:"type,omitempty"` +} + +// MyTradeBreak defines model for MyTrade.Break. +type MyTradeBreak string + +// MyTradeType defines model for MyTrade.Type. +type MyTradeType string + +// MyTradesRequest defines model for MyTradesRequest. +type MyTradesRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // LimitTrades The maximum number of trades to return. Default is 50, max is 500. + LimitTrades *int `json:"limit_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) to retrieve trades for + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// NetworkAssets defines model for NetworkAssets. +type NetworkAssets struct { + // Assets Alphabetically sorted array of enabled asset/token codes available on this network. Assets include both exchange-tradable and custody-supported tokens. + Assets *[]string `json:"assets,omitempty"` + + // Network The blockchain network identifier. + Network *string `json:"network,omitempty"` +} + +// NetworkToken defines model for NetworkToken. +type NetworkToken struct { + // Network Array of supported blockchain networks for the token. Many tokens (especially stablecoins like USDC, USDT) are available on multiple networks. + // + // Supported networks include: `bitcoin`, `ethereum`, `solana`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + Network *[]string `json:"network,omitempty"` + + // Token The requested token identifier. + Token *string `json:"token,omitempty"` +} + +// NewOrderRequest defines model for NewOrderRequest. +type NewOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Amount Quoted decimal amount to purchase + Amount string `json:"amount"` + + // ClientOrderId *Recommended*. A [client-specified order id](/client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // MarginOrder Set to `true` to place this order on a margin account using borrowed funds. Defaults to `false`. Only available for margin-enabled accounts. See [Margin Trading](/margin/account-summary) for details. + MarginOrder *bool `json:"margin_order,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce int64 `json:"nonce"` + + // Options An optional array containing at most one supported order execution option. See Order execution options for details. + Options *[]NewOrderRequestOptions `json:"options,omitempty"` + + // Price Quoted decimal amount to spend per unit + Price string `json:"price"` + + // Request The literal string "/v1/order/new" + Request string `json:"request"` + Side NewOrderRequestSide `json:"side"` + + // StopPrice The price to trigger a stop-limit order. Only available for stop-limit orders. + StopPrice *string `json:"stop_price,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) for the new order + Symbol string `json:"symbol"` + + // Type The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. + Type NewOrderRequestType `json:"type"` +} + +// NewOrderRequestOptions defines model for NewOrderRequest.Options. +type NewOrderRequestOptions string + +// NewOrderRequestSide defines model for NewOrderRequest.Side. +type NewOrderRequestSide string + +// NewOrderRequestType The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. +type NewOrderRequestType string + +// Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Nonce struct { + union json.RawMessage +} + +// Nonce1 defines model for . +type Nonce1 = int64 + +// NotionalBalance defines model for NotionalBalance. +type NotionalBalance struct { + // Amount The current balance + Amount *string `json:"amount,omitempty"` + + // AmountNotional Amount, in notional + AmountNotional *string `json:"amountNotional,omitempty"` + + // Available The amount that is available to trade + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal The amount that is available to withdraw + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // AvailableForWithdrawalNotional AvailableForWithdrawal, in notional + AvailableForWithdrawalNotional *string `json:"availableForWithdrawalNotional,omitempty"` + + // AvailableNotional Available, in notional + AvailableNotional *string `json:"availableNotional,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` +} + +// NotionalVolume defines model for NotionalVolume. +type NotionalVolume struct { + ApiAuctionFeeBps *int `json:"api_auction_fee_bps,omitempty"` + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiNotional30dVolume *string `json:"api_notional_30d_volume,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Date *openapi_types.Date `json:"date,omitempty"` + FeeTier *struct { + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Tier *string `json:"tier,omitempty"` + } `json:"fee_tier,omitempty"` + FixAuctionFeeBps *int `json:"fix_auction_fee_bps,omitempty"` + FixMakerFeeBps *int `json:"fix_maker_fee_bps,omitempty"` + FixTakerFeeBps *int `json:"fix_taker_fee_bps,omitempty"` + LastUpdatedMs *int64 `json:"last_updated_ms,omitempty"` + Notional1dVolume *[]struct { + // Date UTC date in `yyyy-MM-dd` format + Date *string `json:"date,omitempty"` + + // NotionalVolume Notional volume value in USD for this single day + NotionalVolume *string `json:"notional_volume,omitempty"` + } `json:"notional_1d_volume,omitempty"` + Notional30dVolume *string `json:"notional_30d_volume,omitempty"` + WebAuctionFeeBps *int `json:"web_auction_fee_bps,omitempty"` + WebMakerFeeBps *int `json:"web_maker_fee_bps,omitempty"` + WebTakerFeeBps *int `json:"web_taker_fee_bps,omitempty"` +} + +// OpenPosition defines model for OpenPosition. +type OpenPosition struct { + // AverageCost The average price of the current position. + AverageCost *string `json:"average_cost,omitempty"` + + // InstrumentType The type of instrument. Either "spot" or "perp". + InstrumentType *string `json:"instrument_type,omitempty"` + + // MarkPrice The current Mark Price for the Asset or the position. + MarkPrice *string `json:"mark_price,omitempty"` + + // NotionalValue The value of position; calculated as (`quantity` * `mark_price`). Value will be negative for shorts. + NotionalValue *string `json:"notional_value,omitempty"` + + // Quantity The position size. Value will be negative for shorts. + Quantity *string `json:"quantity,omitempty"` + + // RealisedPnl The current P&L that has been realised from the position. + RealisedPnl *string `json:"realised_pnl,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) of the order. + Symbol *string `json:"symbol,omitempty"` + + // UnrealisedPnl Current Mark to Market value of the positions. + UnrealisedPnl *string `json:"unrealised_pnl,omitempty"` +} + +// Order defines model for Order. +type Order struct { + // AvgExecutionPrice The average price at which this order as been executed so far. 0 if the order has not been executed at all. + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + + // ClientOrderId An optional [client-specified order id](/client-order-id#client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // ExecutedAmount The amount of the order that has been filled. + ExecutedAmount *string `json:"executed_amount,omitempty"` + + // IsCancelled `true` if the order has been canceled. Note the spelling, "cancelled" instead of "canceled". This is for compatibility reasons. + IsCancelled *bool `json:"is_cancelled,omitempty"` + + // IsHidden Will always return `false`. + IsHidden *bool `json:"is_hidden,omitempty"` + + // IsLive `true` if the order is active on the book (has remaining quantity and has not been canceled) + IsLive *bool `json:"is_live,omitempty"` + + // Options An array containing at most one supported order execution option. See [Order execution options](/rest/orders#create-new-order) for details. + Options *[]string `json:"options,omitempty"` + + // OrderId The order id + OrderId *string `json:"order_id,omitempty"` + + // OriginalAmount The originally submitted amount of the order. + OriginalAmount *string `json:"original_amount,omitempty"` + + // Price The price the order was issued at + Price *string `json:"price,omitempty"` + + // Reason Populated with the reason your order was canceled, if available. + Reason *string `json:"reason,omitempty"` + + // RemainingAmount The amount of the order that has not been filled. + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *OrderSide `json:"side,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums#symbols-and-minimums) of the order + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Trades Contains an array of JSON objects with trade details. + Trades *[]struct { + // Aggressor If `true`, this order was the taker in the trade + Aggressor *bool `json:"aggressor,omitempty"` + + // Amount The quantity that was executed + Amount *string `json:"amount,omitempty"` + + // Break Will only be present if the trade is broken. See `Break Types` below for more information. + Break *string `json:"break,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The amount charged + FeeAmount *string `json:"fee_amount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"fee_currency,omitempty"` + + // OrderId The order that this trade executed against + OrderId *string `json:"order_id,omitempty"` + + // Price The price that the execution happened at + Price *string `json:"price,omitempty"` + + // Tid Unique identifier for the trade + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type Will be either "Buy" or "Sell", indicating the side of the original order + Type *OrderTradesType `json:"type,omitempty"` + } `json:"trades,omitempty"` + + // Type Description of the order + Type *OrderType `json:"type,omitempty"` + + // WasForced Will always be `false`. + WasForced *bool `json:"was_forced,omitempty"` +} + +// OrderSide defines model for Order.Side. +type OrderSide string + +// OrderTradesType Will be either "Buy" or "Sell", indicating the side of the original order +type OrderTradesType string + +// OrderType Description of the order +type OrderType string + +// OrderBook defines model for OrderBook. +type OrderBook struct { + // Asks The ask price levels currently on the book. These are offers to sell at a given price. + Asks *[]OrderBookEntry `json:"asks,omitempty"` + + // Bids The bid price levels currently on the book. These are offers to buy at a given price. + Bids *[]OrderBookEntry `json:"bids,omitempty"` +} + +// OrderBookEntry defines model for OrderBookEntry. +type OrderBookEntry struct { + // Amount The total quantity remaining at the price + Amount *string `json:"amount,omitempty"` + + // Price The price + Price *string `json:"price,omitempty"` + + // Timestamp **DO NOT USE** - this field is included for compatibility reasons only and is just populated with a dummy value. + Timestamp *string `json:"timestamp,omitempty"` +} + +// OrderStatusRequest defines model for OrderStatusRequest. +type OrderStatusRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // ClientOrderId The `client_order_id` used when placing the order. `client_order_id` cannot be used in combination with `order_id` + ClientOrderId *string `json:"client_order_id,omitempty"` + + // IncludeTrades Either `True` or `False`. If `True` the endpoint will return individual trade details of all fills from the order. + IncludeTrades *bool `json:"include_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order id to get information on. The `order_id` represents a whole number and is transmitted as an unsigned 64-bit integer in JSON format. `order_id` cannot be used in combination with `client_order_id`. + OrderId uint64 `json:"order_id"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// PaymentMethodBalance defines model for PaymentMethodBalance. +type PaymentMethodBalance struct { + // Amount Total account balance for currency. + Amount *string `json:"amount,omitempty"` + + // Available Total amount available for trading + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal Total amount available for withdrawal + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // Currency Symbol for fiat balance. + Currency *string `json:"currency,omitempty"` + + // Type Account type. Will always be `exchange` + Type *string `json:"type,omitempty"` +} + +// PaymentMethodBank defines model for PaymentMethodBank. +type PaymentMethodBank struct { + // Bank Name of bank account + Bank *string `json:"bank,omitempty"` + + // BankId Unique identifier for bank account + BankId *string `json:"bankId,omitempty"` +} + +// PaymentMethodsResponse defines model for PaymentMethodsResponse. +type PaymentMethodsResponse struct { + // Balances Array of JSON objects with available fiat currencies and their balances. + Balances *[]PaymentMethodBalance `json:"balances,omitempty"` + + // Banks Array of JSON objects with banking information + Banks *[]PaymentMethodBank `json:"banks,omitempty"` +} + +// PriceFeedResponse defines model for PriceFeedResponse. +type PriceFeedResponse = []struct { + // Pair Trading pair symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Pair *string `json:"pair,omitempty"` + + // PercentChange24h 24 hour change in price of the pair on the Gemini order book + PercentChange24h *string `json:"percentChange24h,omitempty"` + + // Price Current price of the pair on the Gemini order book + Price *string `json:"price,omitempty"` +} + +// Quantity defines model for Quantity. +type Quantity struct { + // Currency The currency code of the quantity. + Currency string `json:"currency"` + + // Value The value of the quantity. + Value string `json:"value"` +} + +// RevokeOauthTokenResponse defines model for RevokeOauthTokenResponse. +type RevokeOauthTokenResponse struct { + // Message A message that indicates the token has been revoked for the account + Message *string `json:"message,omitempty"` +} + +// RiskStatsResponse defines model for RiskStatsResponse. +type RiskStatsResponse struct { + // IndexPrice Current index price at the time of request + IndexPrice *string `json:"index_price,omitempty"` + + // MarkPrice Current mark price at the time of request + MarkPrice *string `json:"mark_price,omitempty"` + + // OpenInterest string representation of decimal value of open interest + OpenInterest *string `json:"open_interest,omitempty"` + + // OpenInterestNotional string representation of decimal value of open interest notional + OpenInterestNotional *string `json:"open_interest_notional,omitempty"` + + // ProductType Contract type for which the symbol data is fetched + ProductType *RiskStatsResponseProductType `json:"product_type,omitempty"` +} + +// RiskStatsResponseProductType Contract type for which the symbol data is fetched +type RiskStatsResponseProductType string + +// RoleResponse defines model for RoleResponse. +type RoleResponse struct { + // CounterpartyId _Only returned for master-level API keys_. The Gemini clearing counterparty ID associated with the API key making the request. + CounterpartyId *string `json:"counterparty_id,omitempty"` + + // IsAccountAdmin _Only returned for master-level API keys_.`True` if the Administrator role is assigned to the API keys. `False` otherwise. + IsAccountAdmin *bool `json:"isAccountAdmin,omitempty"` + + // IsAuditor `True` if the Auditor role is assigned to the API keys. `False` otherwise. + IsAuditor bool `json:"isAuditor"` + + // IsFundManager `True` if the Fund Manager role is assigned to the API keys. `False` otherwise. + IsFundManager bool `json:"isFundManager"` + + // IsTrader `True` if the Trader role is assigned to the API keys. `False` otherwise. + IsTrader bool `json:"isTrader"` +} + +// StakingBalance defines model for StakingBalance. +type StakingBalance struct { + // Available The amount that is available to trade + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The Staking amount that is available to redeem to exchange account + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Balance The current Staking balance + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + BalanceByProvider *map[string]struct { + // Balance The current Staking balance per providerId + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + } `json:"balanceByProvider,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` + + // Type Will always be "Staking" + Type *string `json:"type,omitempty"` +} + +// StakingDeposit defines model for StakingDeposit. +type StakingDeposit struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rates A JSON object including one or many rates. If more than one rate it would be an array of rates. + Rates *struct { + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *int `json:"rate,omitempty"` + } `json:"rates,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StakingHistory defines model for StakingHistory. +type StakingHistory struct { + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + Transactions *[]StakingTransaction `json:"transactions,omitempty"` +} + +// StakingRate defines model for StakingRate. +type StakingRate struct { + // ApyPct Staking interest APY (Expressed as a percentage derived from the rate and rounded to 1/10th of a percent.) + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // DepositUsdLimit Maximum new amount in USD notional of this crypto that can participate in Gemini Staking per account per month + DepositUsdLimit *int `json:"depositUsdLimit,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *openapi_types.DecimalNumber `json:"rate,omitempty"` + + // RatePct `rate` expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRateProvider Currency Symbol Keys +type StakingRateProvider struct { + CurrencySymbol *StakingRate `json:"currency_symbol,omitempty"` +} + +// StakingRateResponse Provider UUID Keys +type StakingRateResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRateProvider `json:"provider_uuid,omitempty"` +} + +// StakingRewardPeriod defines model for StakingRewardPeriod. +type StakingRewardPeriod struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // ApyPct Staking reward rate expressed as an APY at time of accrual. Interest on Staking balances compounds daily based on the simple rate which is available from `/v1/staking/rates/` + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // FirstAccrualAt Time of first accrual. In iso datetime with timezone format + FirstAccrualAt *string `json:"firstAccrualAt,omitempty"` + + // LastAccrualAt Time of last accrual. In iso datetime with timezone format + LastAccrualAt *string `json:"lastAccrualAt,omitempty"` + + // NumberOfAccruals Number of accruals in the specific aggregate, typically one per day. If the rate is adjusted, new accruals are added. + NumberOfAccruals *int `json:"numberOfAccruals,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePct Rate expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRewards defines model for StakingRewards. +type StakingRewards struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePeriods Array of JSON objects with period accrual information + RatePeriods *[]StakingRewardPeriod `json:"ratePeriods,omitempty"` +} + +// StakingRewardsProvider Currency Symbol Keys +type StakingRewardsProvider struct { + CurrencySymbol *StakingRewards `json:"currency_symbol,omitempty"` +} + +// StakingRewardsResponse Provider UUID Keys +type StakingRewardsResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRewardsProvider `json:"provider_uuid,omitempty"` +} + +// StakingTransaction defines model for StakingTransaction. +type StakingTransaction struct { + // Amount The amount that is defined by the transactionType above + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountCurrency Currency code + AmountCurrency *string `json:"amountCurrency,omitempty"` + + // DateTime timestamp + DateTime *TimestampType `json:"dateTime,omitempty"` + + // PriceAmount Current market price of the underlying token at the time of the reward + PriceAmount *openapi_types.DecimalNumber `json:"priceAmount,omitempty"` + + // PriceCurrency A supported three-letter fiat currency code, e.g. usd + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` + + // TransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment + TransactionType *StakingTransactionTransactionType `json:"transactionType,omitempty"` +} + +// StakingTransactionTransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment +type StakingTransactionTransactionType string + +// StakingWithdrawal defines model for StakingWithdrawal. +type StakingWithdrawal struct { + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountPaidSoFar The amount redeemed successfully + AmountPaidSoFar *openapi_types.DecimalNumber `json:"amountPaidSoFar,omitempty"` + + // AmountRemaining The amount pending to be redeemed + AmountRemaining *openapi_types.DecimalNumber `json:"amountRemaining,omitempty"` + + // Currency Currency code + Currency *string `json:"currency,omitempty"` + + // RequestInitiated In ISO datetime with timezone format + RequestInitiated *string `json:"requestInitiated,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StopLimitOrderResponse defines model for StopLimitOrderResponse. +type StopLimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Side *StopLimitOrderResponseSide `json:"side,omitempty"` + StopPrice *string `json:"stop_price,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *StopLimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// StopLimitOrderResponseSide defines model for StopLimitOrderResponse.Side. +type StopLimitOrderResponseSide string + +// StopLimitOrderResponseType defines model for StopLimitOrderResponse.Type. +type StopLimitOrderResponseType string + +// SymbolDetails defines model for SymbolDetails. +type SymbolDetails struct { + // BaseCurrency CCY1 or the top currency. (i.e `BTC` in `BTCUSD`) + BaseCurrency *string `json:"base_currency,omitempty"` + + // ContractPriceCurrency CCY2 or the quote currency for spot instrument (i.e. `USD` in `BTCUSD`) + // Or collateral currency of the contract in case of perpetual swap instrument. + ContractPriceCurrency *string `json:"contract_price_currency,omitempty"` + + // ContractType `vanilla` / `linear` / `inverse` where `vanilla` is for spot + // while `linear` is for perpetual swap and `inverse` is a special case perpetual swap where the perpetual contract will be settled in base currency. + ContractType *string `json:"contract_type,omitempty"` + + // MinOrderSize The minimum order size in `base_currency` units (i.e `0.00001`) + MinOrderSize *string `json:"min_order_size,omitempty"` + + // ProductType Instrument type `spot` / `swap` -- where `swap` signifies `perpetual swap`. + ProductType *string `json:"product_type,omitempty"` + + // QuoteCurrency CCY2 or the quote currency. (i.e `USD` in `BTCUSD`) + QuoteCurrency *string `json:"quote_currency,omitempty"` + + // QuoteIncrement The number of decimal places in the `quote_currency` (i.e `0.01`) + QuoteIncrement *openapi_types.DecimalNumber `json:"quote_increment,omitempty"` + + // Status Status of the current order book. Can be `open`, `closed`, `cancel_only`, `post_only`, `limit_only`. + Status *string `json:"status,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` + + // TickSize The number of decimal places in the `base_currency`. (i.e `1e-8`) + TickSize *openapi_types.DecimalNumber `json:"tick_size,omitempty"` + + // WrapEnabled When `True`, symbol can be wrapped using this endpoint: + // `POST https://api.gemini.com/v1/wrap/:symbol` + WrapEnabled *bool `json:"wrap_enabled,omitempty"` +} + +// Ticker defines model for Ticker. +type Ticker struct { + // Ask The lowest ask currently available + Ask *string `json:"ask,omitempty"` + + // Bid The highest bid currently available + Bid *string `json:"bid,omitempty"` + + // Last The price of the last executed trade + Last *string `json:"last,omitempty"` + + // Volume Information about the 24 hour volume on the exchange. See properties below + Volume *struct { + // PriceSymbol The volume denominated in the price currency + PriceSymbol *string `json:"price_symbol,omitempty"` + + // QuantitySymbol The volume denominated in the quantity currency + QuantitySymbol *string `json:"quantity_symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + } `json:"volume,omitempty"` +} + +// TickerInfo defines model for TickerInfo. +type TickerInfo struct { + // Ask Current best offer + Ask *string `json:"ask,omitempty"` + + // Bid Current best bid + Bid *string `json:"bid,omitempty"` + + // Changes Hourly prices descending for past 24 hours + Changes *[]string `json:"changes,omitempty"` + + // Close Close price (most recent trade) + Close *string `json:"close,omitempty"` + + // High High price from 24 hours ago + High *string `json:"high,omitempty"` + + // Low Low price from 24 hours ago + Low *string `json:"low,omitempty"` + + // Open Open price from 24 hours ago + Open *string `json:"open,omitempty"` + + // Symbol The trading pair symbol + Symbol *string `json:"symbol,omitempty"` +} + +// TimestampType timestamp +type TimestampType struct { + union json.RawMessage +} + +// TimestampType0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `1495127793` | `POST` only | +// | string (milliseconds) | `1495127793000` | `POST` only | +type TimestampType0 = string + +// TimestampType1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type TimestampType1 = int64 + +// Trade defines model for Trade. +type Trade struct { + // Amount The amount that was traded + Amount *string `json:"amount,omitempty"` + + // Broken Whether the trade was broken or not. Broken trades will not be displayed by default; use the `include_breaks` to display them. + Broken *bool `json:"broken,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // Price The price the trade was executed at + Price *string `json:"price,omitempty"` + + // Tid The trade ID number + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type - `buy` means that an ask was removed from the book by an incoming buy order. + // - `sell` means that a bid was removed from the book by an incoming sell order. + Type *TradeType `json:"type,omitempty"` +} + +// TradeType - `buy` means that an ask was removed from the book by an incoming buy order. +// - `sell` means that a bid was removed from the book by an incoming sell order. +type TradeType string + +// TradeVolume defines model for TradeVolume. +type TradeVolume struct { + BaseCurrency *string `json:"base_currency,omitempty"` + BuyMakerBase *string `json:"buy_maker_base,omitempty"` + BuyMakerCount *int `json:"buy_maker_count,omitempty"` + BuyMakerNotional *string `json:"buy_maker_notional,omitempty"` + BuyTakerBase *string `json:"buy_taker_base,omitempty"` + BuyTakerCount *int `json:"buy_taker_count,omitempty"` + BuyTakerNotional *string `json:"buy_taker_notional,omitempty"` + DataDate *string `json:"data_date,omitempty"` + MakerBuySellRatio *string `json:"maker_buy_sell_ratio,omitempty"` + NotionalCurrency *string `json:"notional_currency,omitempty"` + QuoteCurrency *string `json:"quote_currency,omitempty"` + SellMakerBase *string `json:"sell_maker_base,omitempty"` + SellMakerCount *int `json:"sell_maker_count,omitempty"` + SellMakerNotional *string `json:"sell_maker_notional,omitempty"` + SellTakerBase *string `json:"sell_taker_base,omitempty"` + SellTakerCount *int `json:"sell_taker_count,omitempty"` + SellTakerNotional *string `json:"sell_taker_notional,omitempty"` + Symbol *string `json:"symbol,omitempty"` + TotalVolumeBase *string `json:"total_volume_base,omitempty"` +} + +// Transaction defines model for Transaction. +type Transaction struct { + union json.RawMessage +} + +// Transaction0 Trade Reponse +type Transaction0 struct { + // Account The account. + Account *string `json:"account,omitempty"` + + // Amount The quantity that was executed. + Amount *string `json:"amount,omitempty"` + + // ClientOrderId The client order ID, if defined. Otherwise an empty string. + ClientOrderId *string `json:"clientOrderId,omitempty"` + + // Exchange Will always be "gemini". + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeAssetCode The symbol that the trade was for + FeeAssetCode *string `json:"feeAssetCode,omitempty"` + + // IsAggressor If true, this order was the taker in the trade. + IsAggressor *bool `json:"isAggressor,omitempty"` + + // IsAuctionFill True if the trade was a auction trade and not an on-exchange trade. + IsAuctionFill *bool `json:"isAuctionFill,omitempty"` + + // IsClearingFill True if the trade was a clearing trade and not an on-exchange trade. + IsClearingFill *bool `json:"isClearingFill,omitempty"` + + // OrderId The order that this trade executed against. + OrderId *int64 `json:"orderId,omitempty"` + + // Price The price that the execution happened at. + Price *string `json:"price,omitempty"` + + // Side Indicating the side of the original order. + Side *string `json:"side,omitempty"` + + // Symbol The symbol that the trade was for. + Symbol *string `json:"symbol,omitempty"` + + // Tid The trade ID. + Tid *int64 `json:"tid,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` +} + +// Transaction1 Transfer Reponse +type Transaction1 struct { + // AdvanceEid Deposit advance event ID. + AdvanceEid *int64 `json:"advanceEid,omitempty"` + + // Amount The quantity that was transferred. + Amount *string `json:"amount,omitempty"` + + // BankId Bank ID. + BankId *string `json:"bankId,omitempty"` + + // ClientTransferId Client Transfer ID. Client transfer ID is an optional client-supplied unique identifier for each withdrawal or internal transfer. + ClientTransferId *string `json:"clientTransferId,omitempty"` + + // CorrelationId Correlation ID. + CorrelationId *int64 `json:"correlationId,omitempty"` + + // Currency Currency code, see symbols + Currency *string `json:"currency,omitempty"` + + // Destination The account you are transferring to. + Destination *string `json:"destination,omitempty"` + + // Eid Transfer event id. + Eid *int64 `json:"eid,omitempty"` + + // FeeId Fee ID. + FeeId *string `json:"feeId,omitempty"` + + // Method Type of transfer method. + Method *string `json:"method,omitempty"` + + // OperationReason The operation reason. + OperationReason *string `json:"operationReason,omitempty"` + + // PendingEid Pending event ID. + PendingEid *int64 `json:"pendingEid,omitempty"` + + // Purpose Purpose. + Purpose *string `json:"purpose,omitempty"` + + // Source The account you are transferring from. + Source *string `json:"source,omitempty"` + + // Status The status of the transfer. + Status *string `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TransactionHash Supplies the transaction hash when available. + TransactionHash *string `json:"transactionHash,omitempty"` + + // TransferId Transfer ID. + TransferId *string `json:"transferId,omitempty"` + + // TransferType Transfer type. + TransferType *string `json:"transferType,omitempty"` + + // WithdrawalEid Withdrawal event ID. + WithdrawalEid *int64 `json:"withdrawalEid,omitempty"` + + // WithdrawalId Withdrawal ID. + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// Transfer defines model for Transfer. +type Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Eid The transfer ID + Eid *int64 `json:"eid,omitempty"` + Status *TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The transaction hash if applicable + TxHash *string `json:"txHash,omitempty"` + Type *TransferType `json:"type,omitempty"` +} + +// TransferStatus defines model for Transfer.Status. +type TransferStatus string + +// TransferType defines model for Transfer.Type. +type TransferType string + +// V2Transfer defines model for V2Transfer. +type V2Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Destination The destination address for withdrawals + Destination *string `json:"destination,omitempty"` + + // Eid The transfer event ID + Eid *int64 `json:"eid,omitempty"` + + // FeeAmount The fee charged for the transfer + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency The currency in which the fee was charged + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // Method The transfer method (e.g., `ACH`, `CreditCard`) + Method *string `json:"method,omitempty"` + + // Network The blockchain network the transfer was executed on (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`). Not present for fiat or administrative transfers. + Network *string `json:"network,omitempty"` + + // OutputIdx The output index for withdrawals + OutputIdx *int `json:"outputIdx,omitempty"` + + // Purpose The purpose or reason for administrative transfers + Purpose *string `json:"purpose,omitempty"` + + // Status The status of the transfer + Status *V2TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The on-chain transaction hash, if applicable + TxHash *string `json:"txHash,omitempty"` + + // Type The type of the transfer + Type *V2TransferType `json:"type,omitempty"` + + // WithdrawalId The unique withdrawal identifier + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// V2TransferStatus The status of the transfer +type V2TransferStatus string + +// V2TransferType The type of the transfer +type V2TransferType string + +// WithdrawCryptoFundsResponse Response returned after submitting a v2 cryptocurrency withdrawal. +type WithdrawCryptoFundsResponse struct { + // Address Standard string format of the withdrawal destination address + Address *string `json:"address,omitempty"` + + // Amount The withdrawal amount + Amount *string `json:"amount,omitempty"` + + // Currency The currency code of the withdrawn asset + Currency *string `json:"currency,omitempty"` + + // Fee The fee charged for the withdrawal + Fee *string `json:"fee,omitempty"` + + // WithdrawalId A unique ID for the withdrawal + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// ApiKeyAuth defines model for apiKeyAuth. +type ApiKeyAuth = string + +// CacheControl defines model for cacheControl. +type CacheControl = string + +// ContentLength defines model for contentLength. +type ContentLength = string + +// ContentType defines model for contentType. +type ContentType = string + +// CurrencyParam defines model for currencyParam. +type CurrencyParam = string + +// NetworkParam defines model for networkParam. +type NetworkParam = string + +// PayloadAuth defines model for payloadAuth. +type PayloadAuth = string + +// SignatureAuth defines model for signatureAuth. +type SignatureAuth = string + +// SymbolParam defines model for symbolParam. +type SymbolParam = string + +// TimestampParam timestamp +type TimestampParam = TimestampType + +// ApiKeyIpFilteringFailure defines model for ApiKeyIpFilteringFailure. +type ApiKeyIpFilteringFailure = ErrorResponse + +// BadRequest defines model for BadRequest. +type BadRequest = ErrorResponse + +// InternalError defines model for InternalError. +type InternalError = ErrorResponse + +// NotFound defines model for NotFound. +type NotFound = ErrorResponse + +// TooManyRequests defines model for TooManyRequests. +type TooManyRequests = ErrorResponse + +// Unauthorized defines model for Unauthorized. +type Unauthorized = ErrorResponse + +// apiKeyAuthContextKey is the context key for apiKeyAuth security scheme +type apiKeyAuthContextKey string + +// payloadAuthContextKey is the context key for payloadAuth security scheme +type payloadAuthContextKey string + +// signatureAuthContextKey is the context key for signatureAuth security scheme +type signatureAuthContextKey string + +// ListClearingBrokersJSONBody defines parameters for ListClearingBrokers. +type ListClearingBrokersJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // ExpirationEnd timestamp + ExpirationEnd *TimestampType `json:"expiration_end,omitempty"` + + // ExpirationStart timestamp + ExpirationStart *TimestampType `json:"expiration_start,omitempty"` + + // Funded Default value false if not set + Funded *bool `json:"funded,omitempty"` + + // LimitOrders The maximum number of orders to return + LimitOrders *int `json:"limit_orders,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/clearing/broker/list" + Request string `json:"request"` + + // Status Filter by status + Status *string `json:"status,omitempty"` + + // SubmissionEnd timestamp + SubmissionEnd *TimestampType `json:"submission_end,omitempty"` + + // SubmissionStart timestamp + SubmissionStart *TimestampType `json:"submission_start,omitempty"` + + // Symbol Trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ListClearingBrokersParams defines parameters for ListClearingBrokers. +type ListClearingBrokersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListClearingBrokers200JSONResponseBodyOrdersSourceSide defines parameters for ListClearingBrokers. +type ListClearingBrokers200JSONResponseBodyOrdersSourceSide string + +// CreateNewBrokerOrderJSONBody defines parameters for CreateNewBrokerOrder. +type CreateNewBrokerOrderJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the broker account on which to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Amount Quoted decimal amount to purchase + Amount string `json:"amount"` + + // ExpiresInHrs The number of hours before the trade expires. Your counterparty will need to confirm the order before this time expires. + ExpiresInHrs int `json:"expires_in_hrs"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Price Quoted decimal amount to spend per unit + Price string `json:"price"` + + // Request The literal string "/v1/clearing/broker/new" + Request string `json:"request"` + + // Side "buy" or "sell". This side will be assigned to the `source_counterparty_id`. The opposite side will be sent to the `target_counterparty_id` + Side CreateNewBrokerOrderJSONBodySide `json:"side"` + + // SourceCounterpartyId A symbol that corresponds with the counterparty sourcing the clearing trade + SourceCounterpartyId string `json:"source_counterparty_id"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) of the order + Symbol string `json:"symbol"` + + // TargetCounterpartyId A symbol that corresponds with the counterparty where the clearing trade is targeted + TargetCounterpartyId string `json:"target_counterparty_id"` +} + +// CreateNewBrokerOrderParams defines parameters for CreateNewBrokerOrder. +type CreateNewBrokerOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CreateNewBrokerOrderJSONBodySide defines parameters for CreateNewBrokerOrder. +type CreateNewBrokerOrderJSONBodySide string + +// CancelClearingOrderJSONBody defines parameters for CancelClearingOrder. +type CancelClearingOrderJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // ClearingId The clearing ID + ClearingId string `json:"clearing_id"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/clearing/cancel" + Request string `json:"request"` +} + +// CancelClearingOrderParams defines parameters for CancelClearingOrder. +type CancelClearingOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ConfirmClearingOrderJSONBody defines parameters for ConfirmClearingOrder. +type ConfirmClearingOrderJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Amount The amount to trade + Amount string `json:"amount"` + + // ClearingId The clearing ID + ClearingId string `json:"clearing_id"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Price The price + Price string `json:"price"` + + // Request The literal string "/v1/clearing/confirm" + Request string `json:"request"` + + // Side The direction of the trade + Side ConfirmClearingOrderJSONBodySide `json:"side"` + + // Symbol The trading pair + Symbol string `json:"symbol"` +} + +// ConfirmClearingOrderParams defines parameters for ConfirmClearingOrder. +type ConfirmClearingOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ConfirmClearingOrderJSONBodySide defines parameters for ConfirmClearingOrder. +type ConfirmClearingOrderJSONBodySide string + +// ListClearingOrdersJSONBody defines parameters for ListClearingOrders. +type ListClearingOrdersJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Counterparty counterparty_id or counterparty_alias + Counterparty *string `json:"counterparty,omitempty"` + + // ExpirationEnd timestamp + ExpirationEnd *TimestampType `json:"expiration_end,omitempty"` + + // ExpirationStart timestamp + ExpirationStart *TimestampType `json:"expiration_start,omitempty"` + + // Funded Default value false if not set + Funded *bool `json:"funded,omitempty"` + + // LimitOrders The maximum number of orders to return + LimitOrders *int `json:"limit_orders,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/clearing/list" + Request string `json:"request"` + + // Side "buy" or "sell" + Side *ListClearingOrdersJSONBodySide `json:"side,omitempty"` + + // Status Filter by status + Status *string `json:"status,omitempty"` + + // SubmissionEnd timestamp + SubmissionEnd *TimestampType `json:"submission_end,omitempty"` + + // SubmissionStart timestamp + SubmissionStart *TimestampType `json:"submission_start,omitempty"` + + // Symbol Trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ListClearingOrdersParams defines parameters for ListClearingOrders. +type ListClearingOrdersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListClearingOrdersJSONBodySide defines parameters for ListClearingOrders. +type ListClearingOrdersJSONBodySide string + +// ListClearingOrders200JSONResponseBodyOrdersSide defines parameters for ListClearingOrders. +type ListClearingOrders200JSONResponseBodyOrdersSide string + +// CreateNewClearingOrderJSONBody defines parameters for CreateNewClearingOrder. +type CreateNewClearingOrderJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Amount The amount to trade + Amount string `json:"amount"` + + // CounterpartyId The counterparty ID + CounterpartyId *string `json:"counterparty_id,omitempty"` + + // ExpiresInHrs The number of hours until the order expires + ExpiresInHrs *int `json:"expires_in_hrs,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Price The price + Price string `json:"price"` + + // Request The literal string "/v1/clearing/new" + Request string `json:"request"` + + // Side The direction of the trade + Side CreateNewClearingOrderJSONBodySide `json:"side"` + + // Symbol The trading pair + Symbol string `json:"symbol"` +} + +// CreateNewClearingOrderParams defines parameters for CreateNewClearingOrder. +type CreateNewClearingOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CreateNewClearingOrderJSONBodySide defines parameters for CreateNewClearingOrder. +type CreateNewClearingOrderJSONBodySide string + +// GetClearingOrderJSONBody defines parameters for GetClearingOrder. +type GetClearingOrderJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // ClearingId The clearing ID + ClearingId string `json:"clearing_id"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/clearing/status" + Request string `json:"request"` +} + +// GetClearingOrderParams defines parameters for GetClearingOrder. +type GetClearingOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListClearingTradesJSONBody defines parameters for ListClearingTrades. +type ListClearingTradesJSONBody struct { + // Account Only required when using a master api-key. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // LimitPerAccount The maximum number of clearing trades to return. The default is 100 and the maximum is 300. + LimitPerAccount *int `json:"limit_per_account,omitempty"` + + // LimitTrades The maximum number of trades to return + LimitTrades *int `json:"limit_trades,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/clearing/trades" + Request string `json:"request"` + + // Symbol The trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // TimestampNanos Only return transfers on or after this timestamp in nanos + TimestampNanos *int64 `json:"timestamp_nanos,omitempty"` +} + +// ListClearingTradesParams defines parameters for ListClearingTrades. +type ListClearingTradesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListClearingTrades200JSONResponseBodyResultsSourceSide defines parameters for ListClearingTrades. +type ListClearingTrades200JSONResponseBodyResultsSourceSide string + +// ExecuteInstantOrderJSONBody defines parameters for ExecuteInstantOrder. +type ExecuteInstantOrderJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Fee The fee for the order. fee must match fee returned in the quote + Fee string `json:"fee"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Price The price from the quote. price must match price returned in the quote + Price string `json:"price"` + + // Quantity The quantity of the asset bought or sold. quantity must match quantity returned in the quote + Quantity string `json:"quantity"` + + // QuoteId Unique ID for the quote. quoteId must match quoteId returned in the quote + QuoteId int64 `json:"quoteId"` + + // Request The literal string "/v1/instant/execute" + Request string `json:"request"` + + // Side "buy" or "sell" + Side ExecuteInstantOrderJSONBodySide `json:"side"` + + // Symbol The symbol for the order. + Symbol string `json:"symbol"` +} + +// ExecuteInstantOrderParams defines parameters for ExecuteInstantOrder. +type ExecuteInstantOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ExecuteInstantOrderJSONBodySide defines parameters for ExecuteInstantOrder. +type ExecuteInstantOrderJSONBodySide string + +// GetInstantQuoteJSONBody defines parameters for GetInstantQuote. +type GetInstantQuoteJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // PaymentMethodType Method used to specify payment method in `buy` order. Can be "AccountBalancePaymentType" to use funds available in USD balance held on Gemini, "BankAccountType" to initial an ACH from a linked bank account, or "CardAccountType" to use a linked debit card to fund the purchase. + PaymentMethodType *string `json:"paymentMethodType,omitempty"` + + // PaymentMethodUuid uuid provided as `bankId` in [Payment Methods API](/fund-management#list-payment-methods) + PaymentMethodUuid *string `json:"paymentMethodUuid,omitempty"` + + // Request The literal string "/v1/instant/quote/" + Request string `json:"request"` + + // Side "buy" or "sell" + Side GetInstantQuoteJSONBodySide `json:"side"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) for the order. Instant includes order books denominated in a [supported currency](https://support.gemini.com/hc/en-us/articles/360000032663-Does-Gemini-support-fiat-currencies-other-than-USD), as `CCY2` + Symbol string `json:"symbol"` + + // TotalSpend Quoted decimal amount to spend on the order. Must comply with [stated minimums](/market-data/symbols-and-minimums). The `totalSpend` will be `CCY2` in `buy` orders and `CCY1` in `sell` orders. + TotalSpend string `json:"totalSpend"` +} + +// GetInstantQuoteParams defines parameters for GetInstantQuote. +type GetInstantQuoteParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetInstantQuoteJSONBodySide defines parameters for GetInstantQuote. +type GetInstantQuoteJSONBodySide string + +// ListClearingBrokersJSONRequestBody defines body for ListClearingBrokers for application/json ContentType. +type ListClearingBrokersJSONRequestBody ListClearingBrokersJSONBody + +// CreateNewBrokerOrderJSONRequestBody defines body for CreateNewBrokerOrder for application/json ContentType. +type CreateNewBrokerOrderJSONRequestBody CreateNewBrokerOrderJSONBody + +// CancelClearingOrderJSONRequestBody defines body for CancelClearingOrder for application/json ContentType. +type CancelClearingOrderJSONRequestBody CancelClearingOrderJSONBody + +// ConfirmClearingOrderJSONRequestBody defines body for ConfirmClearingOrder for application/json ContentType. +type ConfirmClearingOrderJSONRequestBody ConfirmClearingOrderJSONBody + +// ListClearingOrdersJSONRequestBody defines body for ListClearingOrders for application/json ContentType. +type ListClearingOrdersJSONRequestBody ListClearingOrdersJSONBody + +// CreateNewClearingOrderJSONRequestBody defines body for CreateNewClearingOrder for application/json ContentType. +type CreateNewClearingOrderJSONRequestBody CreateNewClearingOrderJSONBody + +// GetClearingOrderJSONRequestBody defines body for GetClearingOrder for application/json ContentType. +type GetClearingOrderJSONRequestBody GetClearingOrderJSONBody + +// ListClearingTradesJSONRequestBody defines body for ListClearingTrades for application/json ContentType. +type ListClearingTradesJSONRequestBody ListClearingTradesJSONBody + +// ExecuteInstantOrderJSONRequestBody defines body for ExecuteInstantOrder for application/json ContentType. +type ExecuteInstantOrderJSONRequestBody ExecuteInstantOrderJSONBody + +// GetInstantQuoteJSONRequestBody defines body for GetInstantQuote for application/json ContentType. +type GetInstantQuoteJSONRequestBody GetInstantQuoteJSONBody + +// AsHeartbeatNonce0 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce0 +func (t Heartbeat_Nonce) AsHeartbeatNonce0() (HeartbeatNonce0, error) { + var body HeartbeatNonce0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce0 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) FromHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce0 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsHeartbeatNonce1 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce1 +func (t Heartbeat_Nonce) AsHeartbeatNonce1() (HeartbeatNonce1, error) { + var body HeartbeatNonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce1 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) FromHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce1 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Heartbeat_Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Heartbeat_Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType returns the union data inside the Nonce as a TimestampType +func (t Nonce) AsTimestampType() (TimestampType, error) { + var body TimestampType + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType overwrites any union data inside the Nonce as the provided TimestampType +func (t *Nonce) FromTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType performs a merge with any union data inside the Nonce, using the provided TimestampType +func (t *Nonce) MergeTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNonce1 returns the union data inside the Nonce as a Nonce1 +func (t Nonce) AsNonce1() (Nonce1, error) { + var body Nonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNonce1 overwrites any union data inside the Nonce as the provided Nonce1 +func (t *Nonce) FromNonce1(v Nonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNonce1 performs a merge with any union data inside the Nonce, using the provided Nonce1 +func (t *Nonce) MergeNonce1(v Nonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType0 returns the union data inside the TimestampType as a TimestampType0 +func (t TimestampType) AsTimestampType0() (TimestampType0, error) { + var body TimestampType0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType0 overwrites any union data inside the TimestampType as the provided TimestampType0 +func (t *TimestampType) FromTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType0 performs a merge with any union data inside the TimestampType, using the provided TimestampType0 +func (t *TimestampType) MergeTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTimestampType1 returns the union data inside the TimestampType as a TimestampType1 +func (t TimestampType) AsTimestampType1() (TimestampType1, error) { + var body TimestampType1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType1 overwrites any union data inside the TimestampType as the provided TimestampType1 +func (t *TimestampType) FromTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType1 performs a merge with any union data inside the TimestampType, using the provided TimestampType1 +func (t *TimestampType) MergeTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t TimestampType) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *TimestampType) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTransaction0 returns the union data inside the Transaction as a Transaction0 +func (t Transaction) AsTransaction0() (Transaction0, error) { + var body Transaction0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction0 overwrites any union data inside the Transaction as the provided Transaction0 +func (t *Transaction) FromTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction0 performs a merge with any union data inside the Transaction, using the provided Transaction0 +func (t *Transaction) MergeTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTransaction1 returns the union data inside the Transaction as a Transaction1 +func (t Transaction) AsTransaction1() (Transaction1, error) { + var body Transaction1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction1 overwrites any union data inside the Transaction as the provided Transaction1 +func (t *Transaction) FromTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction1 performs a merge with any union data inside the Transaction, using the provided Transaction1 +func (t *Transaction) MergeTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Transaction) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Transaction) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/packages/sdk-go/generated/clearing/types_runtime_test.go b/packages/sdk-go/generated/clearing/types_runtime_test.go new file mode 100644 index 0000000..6f6a9c8 --- /dev/null +++ b/packages/sdk-go/generated/clearing/types_runtime_test.go @@ -0,0 +1,18 @@ +package clearing_test + +import ( + "encoding/json" + "testing" + + "github.com/gemini/developer-platform/packages/sdk-go/generated/clearing" +) + +func TestClearingOrderTimestampDecodesAsWideInteger(t *testing.T) { + var order clearing.ClearingOrder + if err := json.Unmarshal([]byte(`{"timestampms":1775001600000}`), &order); err != nil { + t.Fatalf("decoding clearing order: %v", err) + } + if order.Timestampms == nil || *order.Timestampms != 1775001600000 { + t.Fatalf("unexpected timestampms: %v", order.Timestampms) + } +} diff --git a/packages/sdk-go/generated/margin/types.gen.go b/packages/sdk-go/generated/margin/types.gen.go new file mode 100644 index 0000000..057e2fc --- /dev/null +++ b/packages/sdk-go/generated/margin/types.gen.go @@ -0,0 +1,2832 @@ +// Code generated from rest.yaml (Margin Trading). DO NOT EDIT. + +// Package margin provides primitives to interact with the openapi HTTP API. +// +// Code generated by oapi-codegen. DO NOT EDIT. +package margin + +import ( + "encoding/json" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/internal/runtime" + openapi_types "github.com/gemini/developer-platform/packages/sdk-go/types" +) + +const ( + ApiKeyAuthScopes apiKeyAuthContextKey = "apiKeyAuth.Scopes" + PayloadAuthScopes payloadAuthContextKey = "payloadAuth.Scopes" + SignatureAuthScopes signatureAuthContextKey = "signatureAuth.Scopes" +) + +// Defines values for BalanceType. +const ( + Exchange BalanceType = "exchange" +) + +// Valid indicates whether the value is a known member of the BalanceType enum. +func (e BalanceType) Valid() bool { + switch e { + case Exchange: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseReason. +const ( + ExceedsPriceLimits CancelOrderResponseReason = "ExceedsPriceLimits" + FillOrKillWouldNotFill CancelOrderResponseReason = "FillOrKillWouldNotFill" + ImmediateOrCancelWouldPost CancelOrderResponseReason = "ImmediateOrCancelWouldPost" + MakerOrCancelWouldTake CancelOrderResponseReason = "MakerOrCancelWouldTake" + MarketClosed CancelOrderResponseReason = "MarketClosed" + Requested CancelOrderResponseReason = "Requested" + SelfCrossPrevented CancelOrderResponseReason = "SelfCrossPrevented" + TradingClosed CancelOrderResponseReason = "TradingClosed" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseReason enum. +func (e CancelOrderResponseReason) Valid() bool { + switch e { + case ExceedsPriceLimits: + return true + case FillOrKillWouldNotFill: + return true + case ImmediateOrCancelWouldPost: + return true + case MakerOrCancelWouldTake: + return true + case MarketClosed: + return true + case Requested: + return true + case SelfCrossPrevented: + return true + case TradingClosed: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseSide. +const ( + CancelOrderResponseSideBuy CancelOrderResponseSide = "buy" + CancelOrderResponseSideSell CancelOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseSide enum. +func (e CancelOrderResponseSide) Valid() bool { + switch e { + case CancelOrderResponseSideBuy: + return true + case CancelOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseType. +const ( + CancelOrderResponseTypeExchangeLimit CancelOrderResponseType = "exchange limit" + CancelOrderResponseTypeExchangeMarket CancelOrderResponseType = "exchange market" + CancelOrderResponseTypeExchangeStopLimit CancelOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseType enum. +func (e CancelOrderResponseType) Valid() bool { + switch e { + case CancelOrderResponseTypeExchangeLimit: + return true + case CancelOrderResponseTypeExchangeMarket: + return true + case CancelOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for ClearingOrderSide. +const ( + ClearingOrderSideBuy ClearingOrderSide = "buy" + ClearingOrderSideSell ClearingOrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the ClearingOrderSide enum. +func (e ClearingOrderSide) Valid() bool { + switch e { + case ClearingOrderSideBuy: + return true + case ClearingOrderSideSell: + return true + default: + return false + } +} + +// Defines values for FundingPaymentEventType. +const ( + FundingPaymentEventTypeHourlyFundingTransfer FundingPaymentEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentEventType enum. +func (e FundingPaymentEventType) Valid() bool { + switch e { + case FundingPaymentEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemAction. +const ( + FundingPaymentReportItemActionCredit FundingPaymentReportItemAction = "Credit" + FundingPaymentReportItemActionDebit FundingPaymentReportItemAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemAction enum. +func (e FundingPaymentReportItemAction) Valid() bool { + switch e { + case FundingPaymentReportItemActionCredit: + return true + case FundingPaymentReportItemActionDebit: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemEventType. +const ( + FundingPaymentReportItemEventTypeHourlyFundingTransfer FundingPaymentReportItemEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemEventType enum. +func (e FundingPaymentReportItemEventType) Valid() bool { + switch e { + case FundingPaymentReportItemEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingTransferAction. +const ( + FundingTransferActionCredit FundingTransferAction = "Credit" + FundingTransferActionDebit FundingTransferAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingTransferAction enum. +func (e FundingTransferAction) Valid() bool { + switch e { + case FundingTransferActionCredit: + return true + case FundingTransferActionDebit: + return true + default: + return false + } +} + +// Defines values for InstantQuoteSide. +const ( + InstantQuoteSideBuy InstantQuoteSide = "buy" + InstantQuoteSideSell InstantQuoteSide = "sell" +) + +// Valid indicates whether the value is a known member of the InstantQuoteSide enum. +func (e InstantQuoteSide) Valid() bool { + switch e { + case InstantQuoteSideBuy: + return true + case InstantQuoteSideSell: + return true + default: + return false + } +} + +// Defines values for InterestRateInfoInterval. +const ( + Hour InterestRateInfoInterval = "hour" +) + +// Valid indicates whether the value is a known member of the InterestRateInfoInterval enum. +func (e InterestRateInfoInterval) Valid() bool { + switch e { + case Hour: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseSide. +const ( + LimitOrderResponseSideBuy LimitOrderResponseSide = "buy" + LimitOrderResponseSideSell LimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseSide enum. +func (e LimitOrderResponseSide) Valid() bool { + switch e { + case LimitOrderResponseSideBuy: + return true + case LimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseType. +const ( + LimitOrderResponseTypeExchangeLimit LimitOrderResponseType = "exchange limit" + LimitOrderResponseTypeExchangeMarket LimitOrderResponseType = "exchange market" + LimitOrderResponseTypeExchangeStopLimit LimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseType enum. +func (e LimitOrderResponseType) Valid() bool { + switch e { + case LimitOrderResponseTypeExchangeLimit: + return true + case LimitOrderResponseTypeExchangeMarket: + return true + case LimitOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for MyTradeBreak. +const ( + Empty MyTradeBreak = "" + TradeCorrect MyTradeBreak = "trade correct" +) + +// Valid indicates whether the value is a known member of the MyTradeBreak enum. +func (e MyTradeBreak) Valid() bool { + switch e { + case Empty: + return true + case TradeCorrect: + return true + default: + return false + } +} + +// Defines values for MyTradeType. +const ( + MyTradeTypeBuy MyTradeType = "Buy" + MyTradeTypeSell MyTradeType = "Sell" +) + +// Valid indicates whether the value is a known member of the MyTradeType enum. +func (e MyTradeType) Valid() bool { + switch e { + case MyTradeTypeBuy: + return true + case MyTradeTypeSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestOptions. +const ( + FillOrKill NewOrderRequestOptions = "fill-or-kill" + ImmediateOrCancel NewOrderRequestOptions = "immediate-or-cancel" + MakerOrCancel NewOrderRequestOptions = "maker-or-cancel" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestOptions enum. +func (e NewOrderRequestOptions) Valid() bool { + switch e { + case FillOrKill: + return true + case ImmediateOrCancel: + return true + case MakerOrCancel: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestSide. +const ( + NewOrderRequestSideBuy NewOrderRequestSide = "buy" + NewOrderRequestSideSell NewOrderRequestSide = "sell" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestSide enum. +func (e NewOrderRequestSide) Valid() bool { + switch e { + case NewOrderRequestSideBuy: + return true + case NewOrderRequestSideSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestType. +const ( + NewOrderRequestTypeExchangeLimit NewOrderRequestType = "exchange limit" + NewOrderRequestTypeExchangeMarket NewOrderRequestType = "exchange market" + NewOrderRequestTypeExchangeStopLimit NewOrderRequestType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestType enum. +func (e NewOrderRequestType) Valid() bool { + switch e { + case NewOrderRequestTypeExchangeLimit: + return true + case NewOrderRequestTypeExchangeMarket: + return true + case NewOrderRequestTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for OrderSide. +const ( + OrderSideBuy OrderSide = "buy" + OrderSideSell OrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the OrderSide enum. +func (e OrderSide) Valid() bool { + switch e { + case OrderSideBuy: + return true + case OrderSideSell: + return true + default: + return false + } +} + +// Defines values for OrderTradesType. +const ( + OrderTradesTypeBuy OrderTradesType = "Buy" + OrderTradesTypeSell OrderTradesType = "Sell" +) + +// Valid indicates whether the value is a known member of the OrderTradesType enum. +func (e OrderTradesType) Valid() bool { + switch e { + case OrderTradesTypeBuy: + return true + case OrderTradesTypeSell: + return true + default: + return false + } +} + +// Defines values for OrderType. +const ( + OrderTypeExchangeLimit OrderType = "exchange limit" + OrderTypeExchangeMarket OrderType = "exchange market" + OrderTypeExchangeStopLimit OrderType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the OrderType enum. +func (e OrderType) Valid() bool { + switch e { + case OrderTypeExchangeLimit: + return true + case OrderTypeExchangeMarket: + return true + case OrderTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for RiskStatsResponseProductType. +const ( + PerpetualSwapContract RiskStatsResponseProductType = "PerpetualSwapContract" +) + +// Valid indicates whether the value is a known member of the RiskStatsResponseProductType enum. +func (e RiskStatsResponseProductType) Valid() bool { + switch e { + case PerpetualSwapContract: + return true + default: + return false + } +} + +// Defines values for StakingTransactionTransactionType. +const ( + StakingTransactionTransactionTypeAdminCreditAdjustment StakingTransactionTransactionType = "AdminCreditAdjustment" + StakingTransactionTransactionTypeAdminDebitAdjustment StakingTransactionTransactionType = "AdminDebitAdjustment" + StakingTransactionTransactionTypeAdminRedeem StakingTransactionTransactionType = "AdminRedeem" + StakingTransactionTransactionTypeDeposit StakingTransactionTransactionType = "Deposit" + StakingTransactionTransactionTypeInterest StakingTransactionTransactionType = "Interest" + StakingTransactionTransactionTypeRedeem StakingTransactionTransactionType = "Redeem" + StakingTransactionTransactionTypeRedeemPayment StakingTransactionTransactionType = "RedeemPayment" +) + +// Valid indicates whether the value is a known member of the StakingTransactionTransactionType enum. +func (e StakingTransactionTransactionType) Valid() bool { + switch e { + case StakingTransactionTransactionTypeAdminCreditAdjustment: + return true + case StakingTransactionTransactionTypeAdminDebitAdjustment: + return true + case StakingTransactionTransactionTypeAdminRedeem: + return true + case StakingTransactionTransactionTypeDeposit: + return true + case StakingTransactionTransactionTypeInterest: + return true + case StakingTransactionTransactionTypeRedeem: + return true + case StakingTransactionTransactionTypeRedeemPayment: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseSide. +const ( + StopLimitOrderResponseSideBuy StopLimitOrderResponseSide = "buy" + StopLimitOrderResponseSideSell StopLimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseSide enum. +func (e StopLimitOrderResponseSide) Valid() bool { + switch e { + case StopLimitOrderResponseSideBuy: + return true + case StopLimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseType. +const ( + ExchangeStopLimit StopLimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseType enum. +func (e StopLimitOrderResponseType) Valid() bool { + switch e { + case ExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for TradeType. +const ( + TradeTypeBuy TradeType = "buy" + TradeTypeSell TradeType = "sell" +) + +// Valid indicates whether the value is a known member of the TradeType enum. +func (e TradeType) Valid() bool { + switch e { + case TradeTypeBuy: + return true + case TradeTypeSell: + return true + default: + return false + } +} + +// Defines values for TransferStatus. +const ( + TransferStatusComplete TransferStatus = "Complete" + TransferStatusPending TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the TransferStatus enum. +func (e TransferStatus) Valid() bool { + switch e { + case TransferStatusComplete: + return true + case TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for TransferType. +const ( + TransferTypeDeposit TransferType = "Deposit" + TransferTypeWithdrawal TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the TransferType enum. +func (e TransferType) Valid() bool { + switch e { + case TransferTypeDeposit: + return true + case TransferTypeWithdrawal: + return true + default: + return false + } +} + +// Defines values for V2TransferStatus. +const ( + V2TransferStatusAdvanced V2TransferStatus = "Advanced" + V2TransferStatusComplete V2TransferStatus = "Complete" + V2TransferStatusPending V2TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the V2TransferStatus enum. +func (e V2TransferStatus) Valid() bool { + switch e { + case V2TransferStatusAdvanced: + return true + case V2TransferStatusComplete: + return true + case V2TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for V2TransferType. +const ( + AdminCredit V2TransferType = "AdminCredit" + AdminDebit V2TransferType = "AdminDebit" + Deposit V2TransferType = "Deposit" + Reward V2TransferType = "Reward" + Withdrawal V2TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the V2TransferType enum. +func (e V2TransferType) Valid() bool { + switch e { + case AdminCredit: + return true + case AdminDebit: + return true + case Deposit: + return true + case Reward: + return true + case Withdrawal: + return true + default: + return false + } +} + +// Defines values for PreviewMarginOrderJSONBodySide. +const ( + Buy PreviewMarginOrderJSONBodySide = "buy" + Sell PreviewMarginOrderJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the PreviewMarginOrderJSONBodySide enum. +func (e PreviewMarginOrderJSONBodySide) Valid() bool { + switch e { + case Buy: + return true + case Sell: + return true + default: + return false + } +} + +// Defines values for PreviewMarginOrderJSONBodyType. +const ( + Limit PreviewMarginOrderJSONBodyType = "limit" + Market PreviewMarginOrderJSONBodyType = "market" +) + +// Valid indicates whether the value is a known member of the PreviewMarginOrderJSONBodyType enum. +func (e PreviewMarginOrderJSONBodyType) Valid() bool { + switch e { + case Limit: + return true + case Market: + return true + default: + return false + } +} + +// Account defines model for Account. +type Account struct { + // AccountId The account ID + AccountId *string `json:"account_id,omitempty"` + + // Created The creation date + Created *string `json:"created,omitempty"` + + // IsDefault Whether the account is the default account + IsDefault *bool `json:"is_default,omitempty"` + + // Name The account name + Name *string `json:"name,omitempty"` +} + +// AddBankResponse defines model for AddBankResponse. +type AddBankResponse struct { + // ReferenceId Reference ID for the new bank addition request. Once received, send in a wire from the requested bank account to verify it and enable withdrawals to that account. + ReferenceId *string `json:"referenceId,omitempty"` + + // Result Status result (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// Address defines model for Address. +type Address struct { + // Address String representation of the cryptocurrency address + Address *string `json:"address,omitempty"` + + // Label If you provided a label when creating the address, it will be echoed back here + Label *string `json:"label,omitempty"` + + // Memo It would be present if applicable, it will be present for cosmos address + Memo *string `json:"memo,omitempty"` + + // Network The blockchain network for the address + Network *string `json:"network,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ApprovedAddress defines model for ApprovedAddress. +type ApprovedAddress struct { + // Address The address on the approved address list. + Address *string `json:"address,omitempty"` + + // CreatedAt UTC timestamp in millisecond of when the address was created. + CreatedAt *string `json:"createdAt,omitempty"` + + // Label The label assigned to the address + Label *string `json:"label,omitempty"` + + // Network The network of the approved address. Network can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Network *string `json:"network,omitempty"` + + // Scope Will return the scope of the address as either "account" or "group" + Scope *string `json:"scope,omitempty"` + + // Status The status of the address that will return as "active", "pending-time" or "pending-mua". The remaining time is exactly 7 days after the initial request. "pending-mua" is for multi-user accounts and will require another administator or fund manager on the account to approve the address. + Status *string `json:"status,omitempty"` +} + +// ApprovedAddressMessage defines model for ApprovedAddressMessage. +type ApprovedAddressMessage struct { + // Message Status or confirmation message for the approved address request or removal. + Message *string `json:"message,omitempty"` + + // Result Result status (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// ApprovedAddressesResponse Response envelope containing the approved withdrawal addresses. +type ApprovedAddressesResponse struct { + // ApprovedAddresses Array of approved addresses on both the account and group level. + ApprovedAddresses *[]ApprovedAddress `json:"approvedAddresses,omitempty"` +} + +// Balance defines model for Balance. +type Balance struct { + // UnderscoreTimestamp Server-side monotonically increasing clock value as an ISO 8601 timestamp. Clients can use this value to detect and filter out stale responses that may occur due to load balancing or potential stale servers. + UnderscoreTimestamp *time.Time `json:"_timestamp,omitempty"` + + // Amount The confirmed balance for the currency (also referred to as `confirmedBalance`). For crypto withdrawals, this value is **not** reduced until the withdrawal has been confirmed on the blockchain. This delay protects against blockchain reorganizations. Use the `available` field instead if you need balances that immediately reflect holds. + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Available The amount available for trading. This value is reduced **immediately** when an order hold or withdrawal hold is placed, making it the recommended field for tracking real-time spendable balances. + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The amount available for withdrawal + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Currency The currency symbol + Currency *string `json:"currency,omitempty"` + + // PendingDeposit The amount pending deposit + PendingDeposit *openapi_types.DecimalNumber `json:"pendingDeposit,omitempty"` + + // PendingWithdrawal The amount pending withdrawal + PendingWithdrawal *openapi_types.DecimalNumber `json:"pendingWithdrawal,omitempty"` + Type *BalanceType `json:"type,omitempty"` +} + +// BalanceType defines model for Balance.Type. +type BalanceType string + +// CancelAllOrdersBySessionRequest defines model for CancelAllOrdersBySessionRequest. +type CancelAllOrdersBySessionRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/session" + Request string `json:"request"` +} + +// CancelAllOrdersRequest defines model for CancelAllOrdersRequest. +type CancelAllOrdersRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/all" + Request string `json:"request"` +} + +// CancelAllResult defines model for CancelAllResult. +type CancelAllResult struct { + // Details cancelledOrders/cancelRejects with IDs of both + Details *struct { + CancelRejects *[]int64 `json:"cancelRejects,omitempty"` + CancelledOrders *[]int64 `json:"cancelledOrders,omitempty"` + } `json:"details,omitempty"` + Result *string `json:"result,omitempty"` +} + +// CancelOrderRequest defines model for CancelOrderRequest. +type CancelOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order ID given by `/order/new` + OrderId uint64 `json:"order_id"` + + // Request The literal string "/v1/order/cancel" + Request string `json:"request"` +} + +// CancelOrderResponse defines model for CancelOrderResponse. +type CancelOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Reason *CancelOrderResponseReason `json:"reason,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *CancelOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *CancelOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// CancelOrderResponseReason defines model for CancelOrderResponse.Reason. +type CancelOrderResponseReason string + +// CancelOrderResponseSide defines model for CancelOrderResponse.Side. +type CancelOrderResponseSide string + +// CancelOrderResponseType defines model for CancelOrderResponse.Type. +type CancelOrderResponseType string + +// Candle defines model for Candle. +type Candle = []float64 + +// CandleResponse defines model for CandleResponse. +type CandleResponse = []Candle + +// ClearingOrder defines model for ClearingOrder. +type ClearingOrder struct { + // Amount The order amount + Amount *string `json:"amount,omitempty"` + + // ClearingId The clearing ID + ClearingId *string `json:"clearing_id,omitempty"` + + // IsConfirmed Whether the order is confirmed + IsConfirmed *bool `json:"is_confirmed,omitempty"` + + // Price The order price + Price *string `json:"price,omitempty"` + Side *ClearingOrderSide `json:"side,omitempty"` + + // Status The order status + Status *string `json:"status,omitempty"` + + // Symbol The trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms The timestamp in milliseconds + Timestampms *int64 `json:"timestampms,omitempty"` +} + +// ClearingOrderSide defines model for ClearingOrder.Side. +type ClearingOrderSide string + +// CustodyFeeTransfer defines model for CustodyFeeTransfer. +type CustodyFeeTransfer struct { + // Eid Custody fee event id + Eid *int64 `json:"eid,omitempty"` + + // EventType Custody fee event type + EventType *string `json:"eventType,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // TxTime Time of Custody fee record in milliseconds + TxTime *int64 `json:"txTime,omitempty"` +} + +// ErrorResponse defines model for ErrorResponse. +type ErrorResponse struct { + // Message Detailed error message + Message *string `json:"message,omitempty"` + + // Reason A short description + Reason *string `json:"reason,omitempty"` + + // Result Error + Result *string `json:"result,omitempty"` +} + +// FeeEstimateRequest defines model for FeeEstimateRequest. +type FeeEstimateRequest struct { + // Account The name of the account within the subaccount group. + Account string `json:"account"` + + // Address Standard string format of cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v1/withdraw/{currencyCodeLowerCase}/feeEstimate` where `:currencyCodeLowerCase` is replaced with the currency code of a supported crypto-currency, e.g. `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateResponse defines model for FeeEstimateResponse. +type FeeEstimateResponse struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated gas fee + Fee *string `json:"fee,omitempty"` + + // IsOverride Value that shows if an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total nunber of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals left to use + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeeEstimateV2Request defines model for FeeEstimateV2Request. +type FeeEstimateV2Request struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Address Standard string format of the destination cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Memo It would be present if applicable, it will be present for cosmos address. + Memo *string `json:"memo,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v2/withdraw/{network}/{ticker}/feeEstimate` where `{network}` is the blockchain network (e.g. `ethereum`, `bitcoin`, `solana`) and `{ticker}` is the currency code (e.g. `eth`, `btc`, `sol`). See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateV2Response defines model for FeeEstimateV2Response. +type FeeEstimateV2Response struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated withdrawal fee as a decimal amount + Fee *openapi_types.DecimalNumber `json:"fee,omitempty"` + + // IsOverride Whether an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total number of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals remaining + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeePromos defines model for FeePromos. +type FeePromos struct { + // Symbols Symbols that currently have fee promos + Symbols *[]string `json:"symbols,omitempty"` +} + +// FundingAmountResponse defines model for FundingAmountResponse. +type FundingAmountResponse struct { + // Amount The dollar amount for a Long 1 position held in the symbol for funding period (1 hour) + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // EstimatedFundingAmount The estimated dollar amount for a Long 1 position held in the symbol for next funding period (1 hour) + EstimatedFundingAmount *openapi_types.DecimalNumber `json:"estimatedFundingAmount,omitempty"` + + // FundingDateTime UTC date time in format `yyyy-MM-ddThh:mm:ss.SSSZ` format + FundingDateTime *string `json:"fundingDateTime,omitempty"` + + // FundingTimestampMilliSecs Current funding amount Epoc time. + FundingTimestampMilliSecs *int64 `json:"fundingTimestampMilliSecs,omitempty"` + + // NextFundingTimestamp Next funding amount Epoc time. + NextFundingTimestamp *int64 `json:"nextFundingTimestamp,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` +} + +// FundingPayment defines model for FundingPayment. +type FundingPayment struct { + // EventType Event type + EventType FundingPaymentEventType `json:"eventType"` + HourlyFundingTransfer FundingTransfer `json:"hourlyFundingTransfer"` +} + +// FundingPaymentEventType Event type +type FundingPaymentEventType string + +// FundingPaymentReportItem defines model for FundingPaymentReportItem. +type FundingPaymentReportItem struct { + // Action Credit or Debit + Action FundingPaymentReportItemAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType FundingPaymentReportItemEventType `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingPaymentReportItemAction Credit or Debit +type FundingPaymentReportItemAction string + +// FundingPaymentReportItemEventType Event type +type FundingPaymentReportItemEventType string + +// FundingTransfer defines model for FundingTransfer. +type FundingTransfer struct { + // Action Credit or Debit + Action FundingTransferAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType string `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingTransferAction Credit or Debit +type FundingTransferAction string + +// FxRate defines model for FxRate. +type FxRate struct { + // AsOf timestamp + AsOf *TimestampType `json:"asOf,omitempty"` + + // Benchmark The market for which the retrieved price applies to + Benchmark *string `json:"benchmark,omitempty"` + + // FxPair The requested currency pair + FxPair *string `json:"fxPair,omitempty"` + + // Provider The market data provider + Provider *string `json:"provider,omitempty"` + + // Rate The exchange rate + Rate *float64 `json:"rate,omitempty"` +} + +// Heartbeat defines model for Heartbeat. +type Heartbeat struct { + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce *Heartbeat_Nonce `json:"nonce,omitempty"` + + // Request The literal string `/v1/heartbeat` + Request *string `json:"request,omitempty"` +} + +// HeartbeatNonce0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `'1495127793'` | `POST` only | +// | string (milliseconds) | `'1495127793000'` | `POST` only | +type HeartbeatNonce0 = string + +// HeartbeatNonce1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type HeartbeatNonce1 = int64 + +// Heartbeat_Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Heartbeat_Nonce struct { + union json.RawMessage +} + +// InstantQuote defines model for InstantQuote. +type InstantQuote struct { + // DepositFee The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + DepositFee *string `json:"depositFee,omitempty"` + + // DepositFeeCurrency Currency in which `depositFee` is taken + DepositFeeCurrency *string `json:"depositFeeCurrency,omitempty"` + + // Fee The fee quantity to be taken for the order upon execution + Fee *string `json:"fee,omitempty"` + + // FeeCurrency The currency label for the order + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // MaxAgeMs Number of milliseconds until this quote price expires. Once expired, you will need to request a new quote + MaxAgeMs *int `json:"maxAgeMs,omitempty"` + + // Pair The symbol passed in the quote request + Pair *string `json:"pair,omitempty"` + + // Price The quoted price of the asset. This will not change when attempting execution + Price *string `json:"price,omitempty"` + + // PriceCurrency The currency in which the order is priced. Matches `CCY2` in the symbol + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // Quantity The quantity of the asset to be bought or sold + Quantity *string `json:"quantity,omitempty"` + + // QuantityCurrency The currency label for the `quantity` field. Matches `CCY1` in the symbol + QuantityCurrency *string `json:"quantityCurrency,omitempty"` + + // QuoteId Unique ID for the quote. This is used in the execution of the order + QuoteId *int64 `json:"quoteId,omitempty"` + + // Side Either "buy" or "sell" + Side *InstantQuoteSide `json:"side,omitempty"` + + // TotalSpend Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + TotalSpend *string `json:"totalSpend,omitempty"` + + // TotalSpendCurrency Currency of the `totalSpend` to be spent on the order + TotalSpendCurrency *string `json:"totalSpendCurrency,omitempty"` +} + +// InstantQuoteSide Either "buy" or "sell" +type InstantQuoteSide string + +// InterestRateInfo defines model for InterestRateInfo. +type InterestRateInfo struct { + // Interval The time interval for the rate (currently only "hour" is supported) + Interval InterestRateInfoInterval `json:"interval"` + + // Rate The interest rate as a decimal string + Rate string `json:"rate"` +} + +// InterestRateInfoInterval The time interval for the rate (currently only "hour" is supported) +type InterestRateInfoInterval string + +// LimitOrderResponse defines model for LimitOrderResponse. +type LimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *LimitOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *LimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// LimitOrderResponseSide defines model for LimitOrderResponse.Side. +type LimitOrderResponseSide string + +// LimitOrderResponseType defines model for LimitOrderResponse.Type. +type LimitOrderResponseType string + +// LiquidationRisk defines model for LiquidationRisk. +type LiquidationRisk struct { + // LiquidationPrice The estimated price at which liquidation would occur (optional, may not be present for all positions) + LiquidationPrice *MoneyAmount `json:"liquidationPrice,omitempty"` + + // LossPercentage The percentage loss from current value that would trigger liquidation, formatted as decimal (e.g., "0.1550" = 15.50%) + LossPercentage string `json:"lossPercentage"` +} + +// MarginAccountSummary defines model for MarginAccountSummary. +type MarginAccountSummary struct { + // AvailableCollateral The amount of collateral available for new positions or withdrawals + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased with available collateral + BuyingPower MoneyAmount `json:"buyingPower"` + + // InterestRate Current interest rate on borrowed amounts (only present if borrows exist) + InterestRate *InterestRateInfo `json:"interestRate,omitempty"` + + // Leverage The current leverage ratio (notionalValue / marginAssetValue) + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if positions exist) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account that can contribute to funding positions + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold with available collateral + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed across all currencies + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MarginInterestRate defines model for MarginInterestRate. +type MarginInterestRate struct { + // BorrowRate The hourly borrow rate as a decimal + BorrowRate string `json:"borrowRate"` + + // BorrowRateAnnual The annualized borrow rate (daily rate × 365) + BorrowRateAnnual string `json:"borrowRateAnnual"` + + // BorrowRateDaily The daily borrow rate (hourly rate × 24) + BorrowRateDaily string `json:"borrowRateDaily"` + + // Currency The currency code (e.g., "BTC", "ETH", "USD") + Currency string `json:"currency"` + + // LastUpdated Unix timestamp in milliseconds when the rate was last updated + LastUpdated int64 `json:"lastUpdated"` +} + +// MarginOrderPreview defines model for MarginOrderPreview. +type MarginOrderPreview struct { + // Postorder Margin risk statistics after the order would be executed + Postorder MarginRiskStats `json:"postorder"` + + // Preorder Margin risk statistics before the order would be executed + Preorder MarginRiskStats `json:"preorder"` +} + +// MarginRatesResponse defines model for MarginRatesResponse. +type MarginRatesResponse struct { + // Rates Array of interest rates for all borrowable currencies + Rates []MarginInterestRate `json:"rates"` +} + +// MarginResponse defines model for MarginResponse. +type MarginResponse struct { + // AvailableMargin The difference between the `margin_assets_value` and `initial_margin`. + AvailableMargin *string `json:"available_margin,omitempty"` + + // BuyingPower The amount of that product the account could purchase based on current `initial_margin` and `margin_assets_value`. + BuyingPower *string `json:"buying_power,omitempty"` + + // EstimatedLiquidationPrice The estimated price for the asset at which liquidation would occur. + EstimatedLiquidationPrice *string `json:"estimated_liquidation_price,omitempty"` + + // InitialMargin The $ amount that is being required by the accounts current positions and open orders. + InitialMargin *string `json:"initial_margin,omitempty"` + + // InitialMarginPositions The contribution to `initial_margin` from open positions. + InitialMarginPositions *string `json:"initial_margin_positions,omitempty"` + + // Leverage The ratio of Notional Value to Margin Assets Value. + Leverage *string `json:"leverage,omitempty"` + + // MarginAssetsValue The $ equivalent value of all the assets available in the current trading account that can contribute to funding a derivatives position. + MarginAssetsValue *string `json:"margin_assets_value,omitempty"` + + // MarginMaintenanceLimit The minimum amount of `margin_assets_value` required before the account is moved to liquidation status. + MarginMaintenanceLimit *string `json:"margin_maintenance_limit,omitempty"` + + // NotionalValue The $ value of the current position. + NotionalValue *string `json:"notional_value,omitempty"` + + // ReservedMargin The contribution to `initial_margin` from open orders. + ReservedMargin *string `json:"reserved_margin,omitempty"` + + // ReservedMarginBuys The contribution to `initial_margin` from open BUY orders. + ReservedMarginBuys *string `json:"reserved_margin_buys,omitempty"` + + // ReservedMarginSells The contribution to `initial_margin` from open SELL orders. + ReservedMarginSells *string `json:"reserved_margin_sells,omitempty"` + + // SellingPower The amount of that product the account could sell based on current `initial_margin` and `margin_assets_value`. + SellingPower *string `json:"selling_power,omitempty"` +} + +// MarginRiskStats defines model for MarginRiskStats. +type MarginRiskStats struct { + // AvailableCollateral The amount of collateral available for new positions + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased + BuyingPower MoneyAmount `json:"buyingPower"` + + // Leverage The leverage ratio + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if applicable) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MoneyAmount defines model for MoneyAmount. +type MoneyAmount struct { + // Currency The currency code (e.g., "USD", "BTC", "ETH") + Currency string `json:"currency"` + + // Value The amount in the specified currency + Value string `json:"value"` +} + +// MyTrade defines model for MyTrade. +type MyTrade struct { + Aggressor *bool `json:"aggressor,omitempty"` + Amount *string `json:"amount,omitempty"` + Break *MyTradeBreak `json:"break,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + FeeAmount *string `json:"fee_amount,omitempty"` + FeeCurrency *string `json:"fee_currency,omitempty"` + IsAuctionFill *bool `json:"is_auction_fill,omitempty"` + OrderId *string `json:"order_id,omitempty"` + Price *string `json:"price,omitempty"` + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *MyTradeType `json:"type,omitempty"` +} + +// MyTradeBreak defines model for MyTrade.Break. +type MyTradeBreak string + +// MyTradeType defines model for MyTrade.Type. +type MyTradeType string + +// MyTradesRequest defines model for MyTradesRequest. +type MyTradesRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // LimitTrades The maximum number of trades to return. Default is 50, max is 500. + LimitTrades *int `json:"limit_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) to retrieve trades for + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// NetworkAssets defines model for NetworkAssets. +type NetworkAssets struct { + // Assets Alphabetically sorted array of enabled asset/token codes available on this network. Assets include both exchange-tradable and custody-supported tokens. + Assets *[]string `json:"assets,omitempty"` + + // Network The blockchain network identifier. + Network *string `json:"network,omitempty"` +} + +// NetworkToken defines model for NetworkToken. +type NetworkToken struct { + // Network Array of supported blockchain networks for the token. Many tokens (especially stablecoins like USDC, USDT) are available on multiple networks. + // + // Supported networks include: `bitcoin`, `ethereum`, `solana`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + Network *[]string `json:"network,omitempty"` + + // Token The requested token identifier. + Token *string `json:"token,omitempty"` +} + +// NewOrderRequest defines model for NewOrderRequest. +type NewOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Amount Quoted decimal amount to purchase + Amount string `json:"amount"` + + // ClientOrderId *Recommended*. A [client-specified order id](/client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // MarginOrder Set to `true` to place this order on a margin account using borrowed funds. Defaults to `false`. Only available for margin-enabled accounts. See [Margin Trading](/margin/account-summary) for details. + MarginOrder *bool `json:"margin_order,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce int64 `json:"nonce"` + + // Options An optional array containing at most one supported order execution option. See Order execution options for details. + Options *[]NewOrderRequestOptions `json:"options,omitempty"` + + // Price Quoted decimal amount to spend per unit + Price string `json:"price"` + + // Request The literal string "/v1/order/new" + Request string `json:"request"` + Side NewOrderRequestSide `json:"side"` + + // StopPrice The price to trigger a stop-limit order. Only available for stop-limit orders. + StopPrice *string `json:"stop_price,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) for the new order + Symbol string `json:"symbol"` + + // Type The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. + Type NewOrderRequestType `json:"type"` +} + +// NewOrderRequestOptions defines model for NewOrderRequest.Options. +type NewOrderRequestOptions string + +// NewOrderRequestSide defines model for NewOrderRequest.Side. +type NewOrderRequestSide string + +// NewOrderRequestType The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. +type NewOrderRequestType string + +// Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Nonce struct { + union json.RawMessage +} + +// Nonce1 defines model for . +type Nonce1 = int64 + +// NotionalBalance defines model for NotionalBalance. +type NotionalBalance struct { + // Amount The current balance + Amount *string `json:"amount,omitempty"` + + // AmountNotional Amount, in notional + AmountNotional *string `json:"amountNotional,omitempty"` + + // Available The amount that is available to trade + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal The amount that is available to withdraw + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // AvailableForWithdrawalNotional AvailableForWithdrawal, in notional + AvailableForWithdrawalNotional *string `json:"availableForWithdrawalNotional,omitempty"` + + // AvailableNotional Available, in notional + AvailableNotional *string `json:"availableNotional,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` +} + +// NotionalVolume defines model for NotionalVolume. +type NotionalVolume struct { + ApiAuctionFeeBps *int `json:"api_auction_fee_bps,omitempty"` + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiNotional30dVolume *string `json:"api_notional_30d_volume,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Date *openapi_types.Date `json:"date,omitempty"` + FeeTier *struct { + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Tier *string `json:"tier,omitempty"` + } `json:"fee_tier,omitempty"` + FixAuctionFeeBps *int `json:"fix_auction_fee_bps,omitempty"` + FixMakerFeeBps *int `json:"fix_maker_fee_bps,omitempty"` + FixTakerFeeBps *int `json:"fix_taker_fee_bps,omitempty"` + LastUpdatedMs *int64 `json:"last_updated_ms,omitempty"` + Notional1dVolume *[]struct { + // Date UTC date in `yyyy-MM-dd` format + Date *string `json:"date,omitempty"` + + // NotionalVolume Notional volume value in USD for this single day + NotionalVolume *string `json:"notional_volume,omitempty"` + } `json:"notional_1d_volume,omitempty"` + Notional30dVolume *string `json:"notional_30d_volume,omitempty"` + WebAuctionFeeBps *int `json:"web_auction_fee_bps,omitempty"` + WebMakerFeeBps *int `json:"web_maker_fee_bps,omitempty"` + WebTakerFeeBps *int `json:"web_taker_fee_bps,omitempty"` +} + +// OpenPosition defines model for OpenPosition. +type OpenPosition struct { + // AverageCost The average price of the current position. + AverageCost *string `json:"average_cost,omitempty"` + + // InstrumentType The type of instrument. Either "spot" or "perp". + InstrumentType *string `json:"instrument_type,omitempty"` + + // MarkPrice The current Mark Price for the Asset or the position. + MarkPrice *string `json:"mark_price,omitempty"` + + // NotionalValue The value of position; calculated as (`quantity` * `mark_price`). Value will be negative for shorts. + NotionalValue *string `json:"notional_value,omitempty"` + + // Quantity The position size. Value will be negative for shorts. + Quantity *string `json:"quantity,omitempty"` + + // RealisedPnl The current P&L that has been realised from the position. + RealisedPnl *string `json:"realised_pnl,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) of the order. + Symbol *string `json:"symbol,omitempty"` + + // UnrealisedPnl Current Mark to Market value of the positions. + UnrealisedPnl *string `json:"unrealised_pnl,omitempty"` +} + +// Order defines model for Order. +type Order struct { + // AvgExecutionPrice The average price at which this order as been executed so far. 0 if the order has not been executed at all. + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + + // ClientOrderId An optional [client-specified order id](/client-order-id#client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // ExecutedAmount The amount of the order that has been filled. + ExecutedAmount *string `json:"executed_amount,omitempty"` + + // IsCancelled `true` if the order has been canceled. Note the spelling, "cancelled" instead of "canceled". This is for compatibility reasons. + IsCancelled *bool `json:"is_cancelled,omitempty"` + + // IsHidden Will always return `false`. + IsHidden *bool `json:"is_hidden,omitempty"` + + // IsLive `true` if the order is active on the book (has remaining quantity and has not been canceled) + IsLive *bool `json:"is_live,omitempty"` + + // Options An array containing at most one supported order execution option. See [Order execution options](/rest/orders#create-new-order) for details. + Options *[]string `json:"options,omitempty"` + + // OrderId The order id + OrderId *string `json:"order_id,omitempty"` + + // OriginalAmount The originally submitted amount of the order. + OriginalAmount *string `json:"original_amount,omitempty"` + + // Price The price the order was issued at + Price *string `json:"price,omitempty"` + + // Reason Populated with the reason your order was canceled, if available. + Reason *string `json:"reason,omitempty"` + + // RemainingAmount The amount of the order that has not been filled. + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *OrderSide `json:"side,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums#symbols-and-minimums) of the order + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Trades Contains an array of JSON objects with trade details. + Trades *[]struct { + // Aggressor If `true`, this order was the taker in the trade + Aggressor *bool `json:"aggressor,omitempty"` + + // Amount The quantity that was executed + Amount *string `json:"amount,omitempty"` + + // Break Will only be present if the trade is broken. See `Break Types` below for more information. + Break *string `json:"break,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The amount charged + FeeAmount *string `json:"fee_amount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"fee_currency,omitempty"` + + // OrderId The order that this trade executed against + OrderId *string `json:"order_id,omitempty"` + + // Price The price that the execution happened at + Price *string `json:"price,omitempty"` + + // Tid Unique identifier for the trade + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type Will be either "Buy" or "Sell", indicating the side of the original order + Type *OrderTradesType `json:"type,omitempty"` + } `json:"trades,omitempty"` + + // Type Description of the order + Type *OrderType `json:"type,omitempty"` + + // WasForced Will always be `false`. + WasForced *bool `json:"was_forced,omitempty"` +} + +// OrderSide defines model for Order.Side. +type OrderSide string + +// OrderTradesType Will be either "Buy" or "Sell", indicating the side of the original order +type OrderTradesType string + +// OrderType Description of the order +type OrderType string + +// OrderBook defines model for OrderBook. +type OrderBook struct { + // Asks The ask price levels currently on the book. These are offers to sell at a given price. + Asks *[]OrderBookEntry `json:"asks,omitempty"` + + // Bids The bid price levels currently on the book. These are offers to buy at a given price. + Bids *[]OrderBookEntry `json:"bids,omitempty"` +} + +// OrderBookEntry defines model for OrderBookEntry. +type OrderBookEntry struct { + // Amount The total quantity remaining at the price + Amount *string `json:"amount,omitempty"` + + // Price The price + Price *string `json:"price,omitempty"` + + // Timestamp **DO NOT USE** - this field is included for compatibility reasons only and is just populated with a dummy value. + Timestamp *string `json:"timestamp,omitempty"` +} + +// OrderStatusRequest defines model for OrderStatusRequest. +type OrderStatusRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // ClientOrderId The `client_order_id` used when placing the order. `client_order_id` cannot be used in combination with `order_id` + ClientOrderId *string `json:"client_order_id,omitempty"` + + // IncludeTrades Either `True` or `False`. If `True` the endpoint will return individual trade details of all fills from the order. + IncludeTrades *bool `json:"include_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order id to get information on. The `order_id` represents a whole number and is transmitted as an unsigned 64-bit integer in JSON format. `order_id` cannot be used in combination with `client_order_id`. + OrderId uint64 `json:"order_id"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// PaymentMethodBalance defines model for PaymentMethodBalance. +type PaymentMethodBalance struct { + // Amount Total account balance for currency. + Amount *string `json:"amount,omitempty"` + + // Available Total amount available for trading + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal Total amount available for withdrawal + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // Currency Symbol for fiat balance. + Currency *string `json:"currency,omitempty"` + + // Type Account type. Will always be `exchange` + Type *string `json:"type,omitempty"` +} + +// PaymentMethodBank defines model for PaymentMethodBank. +type PaymentMethodBank struct { + // Bank Name of bank account + Bank *string `json:"bank,omitempty"` + + // BankId Unique identifier for bank account + BankId *string `json:"bankId,omitempty"` +} + +// PaymentMethodsResponse defines model for PaymentMethodsResponse. +type PaymentMethodsResponse struct { + // Balances Array of JSON objects with available fiat currencies and their balances. + Balances *[]PaymentMethodBalance `json:"balances,omitempty"` + + // Banks Array of JSON objects with banking information + Banks *[]PaymentMethodBank `json:"banks,omitempty"` +} + +// PriceFeedResponse defines model for PriceFeedResponse. +type PriceFeedResponse = []struct { + // Pair Trading pair symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Pair *string `json:"pair,omitempty"` + + // PercentChange24h 24 hour change in price of the pair on the Gemini order book + PercentChange24h *string `json:"percentChange24h,omitempty"` + + // Price Current price of the pair on the Gemini order book + Price *string `json:"price,omitempty"` +} + +// Quantity defines model for Quantity. +type Quantity struct { + // Currency The currency code of the quantity. + Currency string `json:"currency"` + + // Value The value of the quantity. + Value string `json:"value"` +} + +// RevokeOauthTokenResponse defines model for RevokeOauthTokenResponse. +type RevokeOauthTokenResponse struct { + // Message A message that indicates the token has been revoked for the account + Message *string `json:"message,omitempty"` +} + +// RiskStatsResponse defines model for RiskStatsResponse. +type RiskStatsResponse struct { + // IndexPrice Current index price at the time of request + IndexPrice *string `json:"index_price,omitempty"` + + // MarkPrice Current mark price at the time of request + MarkPrice *string `json:"mark_price,omitempty"` + + // OpenInterest string representation of decimal value of open interest + OpenInterest *string `json:"open_interest,omitempty"` + + // OpenInterestNotional string representation of decimal value of open interest notional + OpenInterestNotional *string `json:"open_interest_notional,omitempty"` + + // ProductType Contract type for which the symbol data is fetched + ProductType *RiskStatsResponseProductType `json:"product_type,omitempty"` +} + +// RiskStatsResponseProductType Contract type for which the symbol data is fetched +type RiskStatsResponseProductType string + +// RoleResponse defines model for RoleResponse. +type RoleResponse struct { + // CounterpartyId _Only returned for master-level API keys_. The Gemini clearing counterparty ID associated with the API key making the request. + CounterpartyId *string `json:"counterparty_id,omitempty"` + + // IsAccountAdmin _Only returned for master-level API keys_.`True` if the Administrator role is assigned to the API keys. `False` otherwise. + IsAccountAdmin *bool `json:"isAccountAdmin,omitempty"` + + // IsAuditor `True` if the Auditor role is assigned to the API keys. `False` otherwise. + IsAuditor bool `json:"isAuditor"` + + // IsFundManager `True` if the Fund Manager role is assigned to the API keys. `False` otherwise. + IsFundManager bool `json:"isFundManager"` + + // IsTrader `True` if the Trader role is assigned to the API keys. `False` otherwise. + IsTrader bool `json:"isTrader"` +} + +// StakingBalance defines model for StakingBalance. +type StakingBalance struct { + // Available The amount that is available to trade + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The Staking amount that is available to redeem to exchange account + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Balance The current Staking balance + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + BalanceByProvider *map[string]struct { + // Balance The current Staking balance per providerId + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + } `json:"balanceByProvider,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` + + // Type Will always be "Staking" + Type *string `json:"type,omitempty"` +} + +// StakingDeposit defines model for StakingDeposit. +type StakingDeposit struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rates A JSON object including one or many rates. If more than one rate it would be an array of rates. + Rates *struct { + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *int `json:"rate,omitempty"` + } `json:"rates,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StakingHistory defines model for StakingHistory. +type StakingHistory struct { + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + Transactions *[]StakingTransaction `json:"transactions,omitempty"` +} + +// StakingRate defines model for StakingRate. +type StakingRate struct { + // ApyPct Staking interest APY (Expressed as a percentage derived from the rate and rounded to 1/10th of a percent.) + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // DepositUsdLimit Maximum new amount in USD notional of this crypto that can participate in Gemini Staking per account per month + DepositUsdLimit *int `json:"depositUsdLimit,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *openapi_types.DecimalNumber `json:"rate,omitempty"` + + // RatePct `rate` expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRateProvider Currency Symbol Keys +type StakingRateProvider struct { + CurrencySymbol *StakingRate `json:"currency_symbol,omitempty"` +} + +// StakingRateResponse Provider UUID Keys +type StakingRateResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRateProvider `json:"provider_uuid,omitempty"` +} + +// StakingRewardPeriod defines model for StakingRewardPeriod. +type StakingRewardPeriod struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // ApyPct Staking reward rate expressed as an APY at time of accrual. Interest on Staking balances compounds daily based on the simple rate which is available from `/v1/staking/rates/` + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // FirstAccrualAt Time of first accrual. In iso datetime with timezone format + FirstAccrualAt *string `json:"firstAccrualAt,omitempty"` + + // LastAccrualAt Time of last accrual. In iso datetime with timezone format + LastAccrualAt *string `json:"lastAccrualAt,omitempty"` + + // NumberOfAccruals Number of accruals in the specific aggregate, typically one per day. If the rate is adjusted, new accruals are added. + NumberOfAccruals *int `json:"numberOfAccruals,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePct Rate expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRewards defines model for StakingRewards. +type StakingRewards struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePeriods Array of JSON objects with period accrual information + RatePeriods *[]StakingRewardPeriod `json:"ratePeriods,omitempty"` +} + +// StakingRewardsProvider Currency Symbol Keys +type StakingRewardsProvider struct { + CurrencySymbol *StakingRewards `json:"currency_symbol,omitempty"` +} + +// StakingRewardsResponse Provider UUID Keys +type StakingRewardsResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRewardsProvider `json:"provider_uuid,omitempty"` +} + +// StakingTransaction defines model for StakingTransaction. +type StakingTransaction struct { + // Amount The amount that is defined by the transactionType above + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountCurrency Currency code + AmountCurrency *string `json:"amountCurrency,omitempty"` + + // DateTime timestamp + DateTime *TimestampType `json:"dateTime,omitempty"` + + // PriceAmount Current market price of the underlying token at the time of the reward + PriceAmount *openapi_types.DecimalNumber `json:"priceAmount,omitempty"` + + // PriceCurrency A supported three-letter fiat currency code, e.g. usd + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` + + // TransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment + TransactionType *StakingTransactionTransactionType `json:"transactionType,omitempty"` +} + +// StakingTransactionTransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment +type StakingTransactionTransactionType string + +// StakingWithdrawal defines model for StakingWithdrawal. +type StakingWithdrawal struct { + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountPaidSoFar The amount redeemed successfully + AmountPaidSoFar *openapi_types.DecimalNumber `json:"amountPaidSoFar,omitempty"` + + // AmountRemaining The amount pending to be redeemed + AmountRemaining *openapi_types.DecimalNumber `json:"amountRemaining,omitempty"` + + // Currency Currency code + Currency *string `json:"currency,omitempty"` + + // RequestInitiated In ISO datetime with timezone format + RequestInitiated *string `json:"requestInitiated,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StopLimitOrderResponse defines model for StopLimitOrderResponse. +type StopLimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Side *StopLimitOrderResponseSide `json:"side,omitempty"` + StopPrice *string `json:"stop_price,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *StopLimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// StopLimitOrderResponseSide defines model for StopLimitOrderResponse.Side. +type StopLimitOrderResponseSide string + +// StopLimitOrderResponseType defines model for StopLimitOrderResponse.Type. +type StopLimitOrderResponseType string + +// SymbolDetails defines model for SymbolDetails. +type SymbolDetails struct { + // BaseCurrency CCY1 or the top currency. (i.e `BTC` in `BTCUSD`) + BaseCurrency *string `json:"base_currency,omitempty"` + + // ContractPriceCurrency CCY2 or the quote currency for spot instrument (i.e. `USD` in `BTCUSD`) + // Or collateral currency of the contract in case of perpetual swap instrument. + ContractPriceCurrency *string `json:"contract_price_currency,omitempty"` + + // ContractType `vanilla` / `linear` / `inverse` where `vanilla` is for spot + // while `linear` is for perpetual swap and `inverse` is a special case perpetual swap where the perpetual contract will be settled in base currency. + ContractType *string `json:"contract_type,omitempty"` + + // MinOrderSize The minimum order size in `base_currency` units (i.e `0.00001`) + MinOrderSize *string `json:"min_order_size,omitempty"` + + // ProductType Instrument type `spot` / `swap` -- where `swap` signifies `perpetual swap`. + ProductType *string `json:"product_type,omitempty"` + + // QuoteCurrency CCY2 or the quote currency. (i.e `USD` in `BTCUSD`) + QuoteCurrency *string `json:"quote_currency,omitempty"` + + // QuoteIncrement The number of decimal places in the `quote_currency` (i.e `0.01`) + QuoteIncrement *openapi_types.DecimalNumber `json:"quote_increment,omitempty"` + + // Status Status of the current order book. Can be `open`, `closed`, `cancel_only`, `post_only`, `limit_only`. + Status *string `json:"status,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` + + // TickSize The number of decimal places in the `base_currency`. (i.e `1e-8`) + TickSize *openapi_types.DecimalNumber `json:"tick_size,omitempty"` + + // WrapEnabled When `True`, symbol can be wrapped using this endpoint: + // `POST https://api.gemini.com/v1/wrap/:symbol` + WrapEnabled *bool `json:"wrap_enabled,omitempty"` +} + +// Ticker defines model for Ticker. +type Ticker struct { + // Ask The lowest ask currently available + Ask *string `json:"ask,omitempty"` + + // Bid The highest bid currently available + Bid *string `json:"bid,omitempty"` + + // Last The price of the last executed trade + Last *string `json:"last,omitempty"` + + // Volume Information about the 24 hour volume on the exchange. See properties below + Volume *struct { + // PriceSymbol The volume denominated in the price currency + PriceSymbol *string `json:"price_symbol,omitempty"` + + // QuantitySymbol The volume denominated in the quantity currency + QuantitySymbol *string `json:"quantity_symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + } `json:"volume,omitempty"` +} + +// TickerInfo defines model for TickerInfo. +type TickerInfo struct { + // Ask Current best offer + Ask *string `json:"ask,omitempty"` + + // Bid Current best bid + Bid *string `json:"bid,omitempty"` + + // Changes Hourly prices descending for past 24 hours + Changes *[]string `json:"changes,omitempty"` + + // Close Close price (most recent trade) + Close *string `json:"close,omitempty"` + + // High High price from 24 hours ago + High *string `json:"high,omitempty"` + + // Low Low price from 24 hours ago + Low *string `json:"low,omitempty"` + + // Open Open price from 24 hours ago + Open *string `json:"open,omitempty"` + + // Symbol The trading pair symbol + Symbol *string `json:"symbol,omitempty"` +} + +// TimestampType timestamp +type TimestampType struct { + union json.RawMessage +} + +// TimestampType0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `1495127793` | `POST` only | +// | string (milliseconds) | `1495127793000` | `POST` only | +type TimestampType0 = string + +// TimestampType1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type TimestampType1 = int64 + +// Trade defines model for Trade. +type Trade struct { + // Amount The amount that was traded + Amount *string `json:"amount,omitempty"` + + // Broken Whether the trade was broken or not. Broken trades will not be displayed by default; use the `include_breaks` to display them. + Broken *bool `json:"broken,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // Price The price the trade was executed at + Price *string `json:"price,omitempty"` + + // Tid The trade ID number + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type - `buy` means that an ask was removed from the book by an incoming buy order. + // - `sell` means that a bid was removed from the book by an incoming sell order. + Type *TradeType `json:"type,omitempty"` +} + +// TradeType - `buy` means that an ask was removed from the book by an incoming buy order. +// - `sell` means that a bid was removed from the book by an incoming sell order. +type TradeType string + +// TradeVolume defines model for TradeVolume. +type TradeVolume struct { + BaseCurrency *string `json:"base_currency,omitempty"` + BuyMakerBase *string `json:"buy_maker_base,omitempty"` + BuyMakerCount *int `json:"buy_maker_count,omitempty"` + BuyMakerNotional *string `json:"buy_maker_notional,omitempty"` + BuyTakerBase *string `json:"buy_taker_base,omitempty"` + BuyTakerCount *int `json:"buy_taker_count,omitempty"` + BuyTakerNotional *string `json:"buy_taker_notional,omitempty"` + DataDate *string `json:"data_date,omitempty"` + MakerBuySellRatio *string `json:"maker_buy_sell_ratio,omitempty"` + NotionalCurrency *string `json:"notional_currency,omitempty"` + QuoteCurrency *string `json:"quote_currency,omitempty"` + SellMakerBase *string `json:"sell_maker_base,omitempty"` + SellMakerCount *int `json:"sell_maker_count,omitempty"` + SellMakerNotional *string `json:"sell_maker_notional,omitempty"` + SellTakerBase *string `json:"sell_taker_base,omitempty"` + SellTakerCount *int `json:"sell_taker_count,omitempty"` + SellTakerNotional *string `json:"sell_taker_notional,omitempty"` + Symbol *string `json:"symbol,omitempty"` + TotalVolumeBase *string `json:"total_volume_base,omitempty"` +} + +// Transaction defines model for Transaction. +type Transaction struct { + union json.RawMessage +} + +// Transaction0 Trade Reponse +type Transaction0 struct { + // Account The account. + Account *string `json:"account,omitempty"` + + // Amount The quantity that was executed. + Amount *string `json:"amount,omitempty"` + + // ClientOrderId The client order ID, if defined. Otherwise an empty string. + ClientOrderId *string `json:"clientOrderId,omitempty"` + + // Exchange Will always be "gemini". + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeAssetCode The symbol that the trade was for + FeeAssetCode *string `json:"feeAssetCode,omitempty"` + + // IsAggressor If true, this order was the taker in the trade. + IsAggressor *bool `json:"isAggressor,omitempty"` + + // IsAuctionFill True if the trade was a auction trade and not an on-exchange trade. + IsAuctionFill *bool `json:"isAuctionFill,omitempty"` + + // IsClearingFill True if the trade was a clearing trade and not an on-exchange trade. + IsClearingFill *bool `json:"isClearingFill,omitempty"` + + // OrderId The order that this trade executed against. + OrderId *int64 `json:"orderId,omitempty"` + + // Price The price that the execution happened at. + Price *string `json:"price,omitempty"` + + // Side Indicating the side of the original order. + Side *string `json:"side,omitempty"` + + // Symbol The symbol that the trade was for. + Symbol *string `json:"symbol,omitempty"` + + // Tid The trade ID. + Tid *int64 `json:"tid,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` +} + +// Transaction1 Transfer Reponse +type Transaction1 struct { + // AdvanceEid Deposit advance event ID. + AdvanceEid *int64 `json:"advanceEid,omitempty"` + + // Amount The quantity that was transferred. + Amount *string `json:"amount,omitempty"` + + // BankId Bank ID. + BankId *string `json:"bankId,omitempty"` + + // ClientTransferId Client Transfer ID. Client transfer ID is an optional client-supplied unique identifier for each withdrawal or internal transfer. + ClientTransferId *string `json:"clientTransferId,omitempty"` + + // CorrelationId Correlation ID. + CorrelationId *int64 `json:"correlationId,omitempty"` + + // Currency Currency code, see symbols + Currency *string `json:"currency,omitempty"` + + // Destination The account you are transferring to. + Destination *string `json:"destination,omitempty"` + + // Eid Transfer event id. + Eid *int64 `json:"eid,omitempty"` + + // FeeId Fee ID. + FeeId *string `json:"feeId,omitempty"` + + // Method Type of transfer method. + Method *string `json:"method,omitempty"` + + // OperationReason The operation reason. + OperationReason *string `json:"operationReason,omitempty"` + + // PendingEid Pending event ID. + PendingEid *int64 `json:"pendingEid,omitempty"` + + // Purpose Purpose. + Purpose *string `json:"purpose,omitempty"` + + // Source The account you are transferring from. + Source *string `json:"source,omitempty"` + + // Status The status of the transfer. + Status *string `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TransactionHash Supplies the transaction hash when available. + TransactionHash *string `json:"transactionHash,omitempty"` + + // TransferId Transfer ID. + TransferId *string `json:"transferId,omitempty"` + + // TransferType Transfer type. + TransferType *string `json:"transferType,omitempty"` + + // WithdrawalEid Withdrawal event ID. + WithdrawalEid *int64 `json:"withdrawalEid,omitempty"` + + // WithdrawalId Withdrawal ID. + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// Transfer defines model for Transfer. +type Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Eid The transfer ID + Eid *int64 `json:"eid,omitempty"` + Status *TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The transaction hash if applicable + TxHash *string `json:"txHash,omitempty"` + Type *TransferType `json:"type,omitempty"` +} + +// TransferStatus defines model for Transfer.Status. +type TransferStatus string + +// TransferType defines model for Transfer.Type. +type TransferType string + +// V2Transfer defines model for V2Transfer. +type V2Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Destination The destination address for withdrawals + Destination *string `json:"destination,omitempty"` + + // Eid The transfer event ID + Eid *int64 `json:"eid,omitempty"` + + // FeeAmount The fee charged for the transfer + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency The currency in which the fee was charged + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // Method The transfer method (e.g., `ACH`, `CreditCard`) + Method *string `json:"method,omitempty"` + + // Network The blockchain network the transfer was executed on (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`). Not present for fiat or administrative transfers. + Network *string `json:"network,omitempty"` + + // OutputIdx The output index for withdrawals + OutputIdx *int `json:"outputIdx,omitempty"` + + // Purpose The purpose or reason for administrative transfers + Purpose *string `json:"purpose,omitempty"` + + // Status The status of the transfer + Status *V2TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The on-chain transaction hash, if applicable + TxHash *string `json:"txHash,omitempty"` + + // Type The type of the transfer + Type *V2TransferType `json:"type,omitempty"` + + // WithdrawalId The unique withdrawal identifier + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// V2TransferStatus The status of the transfer +type V2TransferStatus string + +// V2TransferType The type of the transfer +type V2TransferType string + +// WithdrawCryptoFundsResponse Response returned after submitting a v2 cryptocurrency withdrawal. +type WithdrawCryptoFundsResponse struct { + // Address Standard string format of the withdrawal destination address + Address *string `json:"address,omitempty"` + + // Amount The withdrawal amount + Amount *string `json:"amount,omitempty"` + + // Currency The currency code of the withdrawn asset + Currency *string `json:"currency,omitempty"` + + // Fee The fee charged for the withdrawal + Fee *string `json:"fee,omitempty"` + + // WithdrawalId A unique ID for the withdrawal + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// ApiKeyAuth defines model for apiKeyAuth. +type ApiKeyAuth = string + +// CacheControl defines model for cacheControl. +type CacheControl = string + +// ContentLength defines model for contentLength. +type ContentLength = string + +// ContentType defines model for contentType. +type ContentType = string + +// CurrencyParam defines model for currencyParam. +type CurrencyParam = string + +// NetworkParam defines model for networkParam. +type NetworkParam = string + +// PayloadAuth defines model for payloadAuth. +type PayloadAuth = string + +// SignatureAuth defines model for signatureAuth. +type SignatureAuth = string + +// SymbolParam defines model for symbolParam. +type SymbolParam = string + +// TimestampParam timestamp +type TimestampParam = TimestampType + +// ApiKeyIpFilteringFailure defines model for ApiKeyIpFilteringFailure. +type ApiKeyIpFilteringFailure = ErrorResponse + +// BadRequest defines model for BadRequest. +type BadRequest = ErrorResponse + +// InternalError defines model for InternalError. +type InternalError = ErrorResponse + +// NotFound defines model for NotFound. +type NotFound = ErrorResponse + +// TooManyRequests defines model for TooManyRequests. +type TooManyRequests = ErrorResponse + +// Unauthorized defines model for Unauthorized. +type Unauthorized = ErrorResponse + +// apiKeyAuthContextKey is the context key for apiKeyAuth security scheme +type apiKeyAuthContextKey string + +// payloadAuthContextKey is the context key for payloadAuth security scheme +type payloadAuthContextKey string + +// signatureAuthContextKey is the context key for signatureAuth security scheme +type signatureAuthContextKey string + +// GetMarginAccountJSONBody defines parameters for GetMarginAccount. +type GetMarginAccountJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/margin/account" + Request string `json:"request"` +} + +// GetMarginAccountParams defines parameters for GetMarginAccount. +type GetMarginAccountParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// PreviewMarginOrderJSONBody defines parameters for PreviewMarginOrder. +type PreviewMarginOrderJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Amount The order amount in base currency (required for limit orders and sell market orders) + Amount *string `json:"amount,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Price The limit price (required for limit orders) + Price *string `json:"price,omitempty"` + + // Request The literal string "/v1/margin/order/preview" + Request string `json:"request"` + + // Side The order side + Side PreviewMarginOrderJSONBodySide `json:"side"` + + // Symbol The trading pair symbol (e.g., "btcusd") + Symbol string `json:"symbol"` + + // TotalSpend Total spend in quote currency (required for buy market orders) + TotalSpend *string `json:"totalSpend,omitempty"` + + // Type The order type + Type PreviewMarginOrderJSONBodyType `json:"type"` +} + +// PreviewMarginOrderParams defines parameters for PreviewMarginOrder. +type PreviewMarginOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// PreviewMarginOrderJSONBodySide defines parameters for PreviewMarginOrder. +type PreviewMarginOrderJSONBodySide string + +// PreviewMarginOrderJSONBodyType defines parameters for PreviewMarginOrder. +type PreviewMarginOrderJSONBodyType string + +// GetMarginRatesJSONBody defines parameters for GetMarginRates. +type GetMarginRatesJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/margin/rates" + Request string `json:"request"` +} + +// GetMarginRatesParams defines parameters for GetMarginRates. +type GetMarginRatesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetMarginAccountJSONRequestBody defines body for GetMarginAccount for application/json ContentType. +type GetMarginAccountJSONRequestBody GetMarginAccountJSONBody + +// PreviewMarginOrderJSONRequestBody defines body for PreviewMarginOrder for application/json ContentType. +type PreviewMarginOrderJSONRequestBody PreviewMarginOrderJSONBody + +// GetMarginRatesJSONRequestBody defines body for GetMarginRates for application/json ContentType. +type GetMarginRatesJSONRequestBody GetMarginRatesJSONBody + +// AsHeartbeatNonce0 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce0 +func (t Heartbeat_Nonce) AsHeartbeatNonce0() (HeartbeatNonce0, error) { + var body HeartbeatNonce0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce0 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) FromHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce0 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsHeartbeatNonce1 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce1 +func (t Heartbeat_Nonce) AsHeartbeatNonce1() (HeartbeatNonce1, error) { + var body HeartbeatNonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce1 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) FromHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce1 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Heartbeat_Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Heartbeat_Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType returns the union data inside the Nonce as a TimestampType +func (t Nonce) AsTimestampType() (TimestampType, error) { + var body TimestampType + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType overwrites any union data inside the Nonce as the provided TimestampType +func (t *Nonce) FromTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType performs a merge with any union data inside the Nonce, using the provided TimestampType +func (t *Nonce) MergeTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNonce1 returns the union data inside the Nonce as a Nonce1 +func (t Nonce) AsNonce1() (Nonce1, error) { + var body Nonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNonce1 overwrites any union data inside the Nonce as the provided Nonce1 +func (t *Nonce) FromNonce1(v Nonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNonce1 performs a merge with any union data inside the Nonce, using the provided Nonce1 +func (t *Nonce) MergeNonce1(v Nonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType0 returns the union data inside the TimestampType as a TimestampType0 +func (t TimestampType) AsTimestampType0() (TimestampType0, error) { + var body TimestampType0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType0 overwrites any union data inside the TimestampType as the provided TimestampType0 +func (t *TimestampType) FromTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType0 performs a merge with any union data inside the TimestampType, using the provided TimestampType0 +func (t *TimestampType) MergeTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTimestampType1 returns the union data inside the TimestampType as a TimestampType1 +func (t TimestampType) AsTimestampType1() (TimestampType1, error) { + var body TimestampType1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType1 overwrites any union data inside the TimestampType as the provided TimestampType1 +func (t *TimestampType) FromTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType1 performs a merge with any union data inside the TimestampType, using the provided TimestampType1 +func (t *TimestampType) MergeTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t TimestampType) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *TimestampType) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTransaction0 returns the union data inside the Transaction as a Transaction0 +func (t Transaction) AsTransaction0() (Transaction0, error) { + var body Transaction0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction0 overwrites any union data inside the Transaction as the provided Transaction0 +func (t *Transaction) FromTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction0 performs a merge with any union data inside the Transaction, using the provided Transaction0 +func (t *Transaction) MergeTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTransaction1 returns the union data inside the Transaction as a Transaction1 +func (t Transaction) AsTransaction1() (Transaction1, error) { + var body Transaction1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction1 overwrites any union data inside the Transaction as the provided Transaction1 +func (t *Transaction) FromTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction1 performs a merge with any union data inside the Transaction, using the provided Transaction1 +func (t *Transaction) MergeTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Transaction) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Transaction) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/packages/sdk-go/generated/marketdata/types.gen.go b/packages/sdk-go/generated/marketdata/types.gen.go new file mode 100644 index 0000000..941bbe6 --- /dev/null +++ b/packages/sdk-go/generated/marketdata/types.gen.go @@ -0,0 +1,2822 @@ +// Code generated from rest.yaml (Market Data). DO NOT EDIT. + +// Package marketdata provides primitives to interact with the openapi HTTP API. +// +// Code generated by oapi-codegen. DO NOT EDIT. +package marketdata + +import ( + "encoding/json" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/internal/runtime" + openapi_types "github.com/gemini/developer-platform/packages/sdk-go/types" +) + +const ( + ApiKeyAuthScopes apiKeyAuthContextKey = "apiKeyAuth.Scopes" + PayloadAuthScopes payloadAuthContextKey = "payloadAuth.Scopes" + SignatureAuthScopes signatureAuthContextKey = "signatureAuth.Scopes" +) + +// Defines values for BalanceType. +const ( + Exchange BalanceType = "exchange" +) + +// Valid indicates whether the value is a known member of the BalanceType enum. +func (e BalanceType) Valid() bool { + switch e { + case Exchange: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseReason. +const ( + ExceedsPriceLimits CancelOrderResponseReason = "ExceedsPriceLimits" + FillOrKillWouldNotFill CancelOrderResponseReason = "FillOrKillWouldNotFill" + ImmediateOrCancelWouldPost CancelOrderResponseReason = "ImmediateOrCancelWouldPost" + MakerOrCancelWouldTake CancelOrderResponseReason = "MakerOrCancelWouldTake" + MarketClosed CancelOrderResponseReason = "MarketClosed" + Requested CancelOrderResponseReason = "Requested" + SelfCrossPrevented CancelOrderResponseReason = "SelfCrossPrevented" + TradingClosed CancelOrderResponseReason = "TradingClosed" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseReason enum. +func (e CancelOrderResponseReason) Valid() bool { + switch e { + case ExceedsPriceLimits: + return true + case FillOrKillWouldNotFill: + return true + case ImmediateOrCancelWouldPost: + return true + case MakerOrCancelWouldTake: + return true + case MarketClosed: + return true + case Requested: + return true + case SelfCrossPrevented: + return true + case TradingClosed: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseSide. +const ( + CancelOrderResponseSideBuy CancelOrderResponseSide = "buy" + CancelOrderResponseSideSell CancelOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseSide enum. +func (e CancelOrderResponseSide) Valid() bool { + switch e { + case CancelOrderResponseSideBuy: + return true + case CancelOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseType. +const ( + CancelOrderResponseTypeExchangeLimit CancelOrderResponseType = "exchange limit" + CancelOrderResponseTypeExchangeMarket CancelOrderResponseType = "exchange market" + CancelOrderResponseTypeExchangeStopLimit CancelOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseType enum. +func (e CancelOrderResponseType) Valid() bool { + switch e { + case CancelOrderResponseTypeExchangeLimit: + return true + case CancelOrderResponseTypeExchangeMarket: + return true + case CancelOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for ClearingOrderSide. +const ( + ClearingOrderSideBuy ClearingOrderSide = "buy" + ClearingOrderSideSell ClearingOrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the ClearingOrderSide enum. +func (e ClearingOrderSide) Valid() bool { + switch e { + case ClearingOrderSideBuy: + return true + case ClearingOrderSideSell: + return true + default: + return false + } +} + +// Defines values for FundingPaymentEventType. +const ( + FundingPaymentEventTypeHourlyFundingTransfer FundingPaymentEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentEventType enum. +func (e FundingPaymentEventType) Valid() bool { + switch e { + case FundingPaymentEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemAction. +const ( + FundingPaymentReportItemActionCredit FundingPaymentReportItemAction = "Credit" + FundingPaymentReportItemActionDebit FundingPaymentReportItemAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemAction enum. +func (e FundingPaymentReportItemAction) Valid() bool { + switch e { + case FundingPaymentReportItemActionCredit: + return true + case FundingPaymentReportItemActionDebit: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemEventType. +const ( + FundingPaymentReportItemEventTypeHourlyFundingTransfer FundingPaymentReportItemEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemEventType enum. +func (e FundingPaymentReportItemEventType) Valid() bool { + switch e { + case FundingPaymentReportItemEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingTransferAction. +const ( + FundingTransferActionCredit FundingTransferAction = "Credit" + FundingTransferActionDebit FundingTransferAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingTransferAction enum. +func (e FundingTransferAction) Valid() bool { + switch e { + case FundingTransferActionCredit: + return true + case FundingTransferActionDebit: + return true + default: + return false + } +} + +// Defines values for InstantQuoteSide. +const ( + InstantQuoteSideBuy InstantQuoteSide = "buy" + InstantQuoteSideSell InstantQuoteSide = "sell" +) + +// Valid indicates whether the value is a known member of the InstantQuoteSide enum. +func (e InstantQuoteSide) Valid() bool { + switch e { + case InstantQuoteSideBuy: + return true + case InstantQuoteSideSell: + return true + default: + return false + } +} + +// Defines values for InterestRateInfoInterval. +const ( + Hour InterestRateInfoInterval = "hour" +) + +// Valid indicates whether the value is a known member of the InterestRateInfoInterval enum. +func (e InterestRateInfoInterval) Valid() bool { + switch e { + case Hour: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseSide. +const ( + LimitOrderResponseSideBuy LimitOrderResponseSide = "buy" + LimitOrderResponseSideSell LimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseSide enum. +func (e LimitOrderResponseSide) Valid() bool { + switch e { + case LimitOrderResponseSideBuy: + return true + case LimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseType. +const ( + LimitOrderResponseTypeExchangeLimit LimitOrderResponseType = "exchange limit" + LimitOrderResponseTypeExchangeMarket LimitOrderResponseType = "exchange market" + LimitOrderResponseTypeExchangeStopLimit LimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseType enum. +func (e LimitOrderResponseType) Valid() bool { + switch e { + case LimitOrderResponseTypeExchangeLimit: + return true + case LimitOrderResponseTypeExchangeMarket: + return true + case LimitOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for MyTradeBreak. +const ( + Empty MyTradeBreak = "" + TradeCorrect MyTradeBreak = "trade correct" +) + +// Valid indicates whether the value is a known member of the MyTradeBreak enum. +func (e MyTradeBreak) Valid() bool { + switch e { + case Empty: + return true + case TradeCorrect: + return true + default: + return false + } +} + +// Defines values for MyTradeType. +const ( + MyTradeTypeBuy MyTradeType = "Buy" + MyTradeTypeSell MyTradeType = "Sell" +) + +// Valid indicates whether the value is a known member of the MyTradeType enum. +func (e MyTradeType) Valid() bool { + switch e { + case MyTradeTypeBuy: + return true + case MyTradeTypeSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestOptions. +const ( + FillOrKill NewOrderRequestOptions = "fill-or-kill" + ImmediateOrCancel NewOrderRequestOptions = "immediate-or-cancel" + MakerOrCancel NewOrderRequestOptions = "maker-or-cancel" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestOptions enum. +func (e NewOrderRequestOptions) Valid() bool { + switch e { + case FillOrKill: + return true + case ImmediateOrCancel: + return true + case MakerOrCancel: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestSide. +const ( + NewOrderRequestSideBuy NewOrderRequestSide = "buy" + NewOrderRequestSideSell NewOrderRequestSide = "sell" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestSide enum. +func (e NewOrderRequestSide) Valid() bool { + switch e { + case NewOrderRequestSideBuy: + return true + case NewOrderRequestSideSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestType. +const ( + NewOrderRequestTypeExchangeLimit NewOrderRequestType = "exchange limit" + NewOrderRequestTypeExchangeMarket NewOrderRequestType = "exchange market" + NewOrderRequestTypeExchangeStopLimit NewOrderRequestType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestType enum. +func (e NewOrderRequestType) Valid() bool { + switch e { + case NewOrderRequestTypeExchangeLimit: + return true + case NewOrderRequestTypeExchangeMarket: + return true + case NewOrderRequestTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for OrderSide. +const ( + OrderSideBuy OrderSide = "buy" + OrderSideSell OrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the OrderSide enum. +func (e OrderSide) Valid() bool { + switch e { + case OrderSideBuy: + return true + case OrderSideSell: + return true + default: + return false + } +} + +// Defines values for OrderTradesType. +const ( + OrderTradesTypeBuy OrderTradesType = "Buy" + OrderTradesTypeSell OrderTradesType = "Sell" +) + +// Valid indicates whether the value is a known member of the OrderTradesType enum. +func (e OrderTradesType) Valid() bool { + switch e { + case OrderTradesTypeBuy: + return true + case OrderTradesTypeSell: + return true + default: + return false + } +} + +// Defines values for OrderType. +const ( + OrderTypeExchangeLimit OrderType = "exchange limit" + OrderTypeExchangeMarket OrderType = "exchange market" + OrderTypeExchangeStopLimit OrderType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the OrderType enum. +func (e OrderType) Valid() bool { + switch e { + case OrderTypeExchangeLimit: + return true + case OrderTypeExchangeMarket: + return true + case OrderTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for RiskStatsResponseProductType. +const ( + PerpetualSwapContract RiskStatsResponseProductType = "PerpetualSwapContract" +) + +// Valid indicates whether the value is a known member of the RiskStatsResponseProductType enum. +func (e RiskStatsResponseProductType) Valid() bool { + switch e { + case PerpetualSwapContract: + return true + default: + return false + } +} + +// Defines values for StakingTransactionTransactionType. +const ( + StakingTransactionTransactionTypeAdminCreditAdjustment StakingTransactionTransactionType = "AdminCreditAdjustment" + StakingTransactionTransactionTypeAdminDebitAdjustment StakingTransactionTransactionType = "AdminDebitAdjustment" + StakingTransactionTransactionTypeAdminRedeem StakingTransactionTransactionType = "AdminRedeem" + StakingTransactionTransactionTypeDeposit StakingTransactionTransactionType = "Deposit" + StakingTransactionTransactionTypeInterest StakingTransactionTransactionType = "Interest" + StakingTransactionTransactionTypeRedeem StakingTransactionTransactionType = "Redeem" + StakingTransactionTransactionTypeRedeemPayment StakingTransactionTransactionType = "RedeemPayment" +) + +// Valid indicates whether the value is a known member of the StakingTransactionTransactionType enum. +func (e StakingTransactionTransactionType) Valid() bool { + switch e { + case StakingTransactionTransactionTypeAdminCreditAdjustment: + return true + case StakingTransactionTransactionTypeAdminDebitAdjustment: + return true + case StakingTransactionTransactionTypeAdminRedeem: + return true + case StakingTransactionTransactionTypeDeposit: + return true + case StakingTransactionTransactionTypeInterest: + return true + case StakingTransactionTransactionTypeRedeem: + return true + case StakingTransactionTransactionTypeRedeemPayment: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseSide. +const ( + StopLimitOrderResponseSideBuy StopLimitOrderResponseSide = "buy" + StopLimitOrderResponseSideSell StopLimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseSide enum. +func (e StopLimitOrderResponseSide) Valid() bool { + switch e { + case StopLimitOrderResponseSideBuy: + return true + case StopLimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseType. +const ( + ExchangeStopLimit StopLimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseType enum. +func (e StopLimitOrderResponseType) Valid() bool { + switch e { + case ExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for TradeType. +const ( + TradeTypeBuy TradeType = "buy" + TradeTypeSell TradeType = "sell" +) + +// Valid indicates whether the value is a known member of the TradeType enum. +func (e TradeType) Valid() bool { + switch e { + case TradeTypeBuy: + return true + case TradeTypeSell: + return true + default: + return false + } +} + +// Defines values for TransferStatus. +const ( + TransferStatusComplete TransferStatus = "Complete" + TransferStatusPending TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the TransferStatus enum. +func (e TransferStatus) Valid() bool { + switch e { + case TransferStatusComplete: + return true + case TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for TransferType. +const ( + TransferTypeDeposit TransferType = "Deposit" + TransferTypeWithdrawal TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the TransferType enum. +func (e TransferType) Valid() bool { + switch e { + case TransferTypeDeposit: + return true + case TransferTypeWithdrawal: + return true + default: + return false + } +} + +// Defines values for V2TransferStatus. +const ( + V2TransferStatusAdvanced V2TransferStatus = "Advanced" + V2TransferStatusComplete V2TransferStatus = "Complete" + V2TransferStatusPending V2TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the V2TransferStatus enum. +func (e V2TransferStatus) Valid() bool { + switch e { + case V2TransferStatusAdvanced: + return true + case V2TransferStatusComplete: + return true + case V2TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for V2TransferType. +const ( + AdminCredit V2TransferType = "AdminCredit" + AdminDebit V2TransferType = "AdminDebit" + Deposit V2TransferType = "Deposit" + Reward V2TransferType = "Reward" + Withdrawal V2TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the V2TransferType enum. +func (e V2TransferType) Valid() bool { + switch e { + case AdminCredit: + return true + case AdminDebit: + return true + case Deposit: + return true + case Reward: + return true + case Withdrawal: + return true + default: + return false + } +} + +// Defines values for ListCandlesParamsTimeFrame. +const ( + ListCandlesParamsTimeFrameN15m ListCandlesParamsTimeFrame = "15m" + ListCandlesParamsTimeFrameN1d ListCandlesParamsTimeFrame = "1d" + ListCandlesParamsTimeFrameN1h ListCandlesParamsTimeFrame = "1h" + ListCandlesParamsTimeFrameN1m ListCandlesParamsTimeFrame = "1m" + ListCandlesParamsTimeFrameN30m ListCandlesParamsTimeFrame = "30m" + ListCandlesParamsTimeFrameN5m ListCandlesParamsTimeFrame = "5m" + ListCandlesParamsTimeFrameN6h ListCandlesParamsTimeFrame = "6h" +) + +// Valid indicates whether the value is a known member of the ListCandlesParamsTimeFrame enum. +func (e ListCandlesParamsTimeFrame) Valid() bool { + switch e { + case ListCandlesParamsTimeFrameN15m: + return true + case ListCandlesParamsTimeFrameN1d: + return true + case ListCandlesParamsTimeFrameN1h: + return true + case ListCandlesParamsTimeFrameN1m: + return true + case ListCandlesParamsTimeFrameN30m: + return true + case ListCandlesParamsTimeFrameN5m: + return true + case ListCandlesParamsTimeFrameN6h: + return true + default: + return false + } +} + +// Defines values for ListDerivativeCandlesParamsTimeFrame. +const ( + ListDerivativeCandlesParamsTimeFrameN1m ListDerivativeCandlesParamsTimeFrame = "1m" +) + +// Valid indicates whether the value is a known member of the ListDerivativeCandlesParamsTimeFrame enum. +func (e ListDerivativeCandlesParamsTimeFrame) Valid() bool { + switch e { + case ListDerivativeCandlesParamsTimeFrameN1m: + return true + default: + return false + } +} + +// Account defines model for Account. +type Account struct { + // AccountId The account ID + AccountId *string `json:"account_id,omitempty"` + + // Created The creation date + Created *string `json:"created,omitempty"` + + // IsDefault Whether the account is the default account + IsDefault *bool `json:"is_default,omitempty"` + + // Name The account name + Name *string `json:"name,omitempty"` +} + +// AddBankResponse defines model for AddBankResponse. +type AddBankResponse struct { + // ReferenceId Reference ID for the new bank addition request. Once received, send in a wire from the requested bank account to verify it and enable withdrawals to that account. + ReferenceId *string `json:"referenceId,omitempty"` + + // Result Status result (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// Address defines model for Address. +type Address struct { + // Address String representation of the cryptocurrency address + Address *string `json:"address,omitempty"` + + // Label If you provided a label when creating the address, it will be echoed back here + Label *string `json:"label,omitempty"` + + // Memo It would be present if applicable, it will be present for cosmos address + Memo *string `json:"memo,omitempty"` + + // Network The blockchain network for the address + Network *string `json:"network,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ApprovedAddress defines model for ApprovedAddress. +type ApprovedAddress struct { + // Address The address on the approved address list. + Address *string `json:"address,omitempty"` + + // CreatedAt UTC timestamp in millisecond of when the address was created. + CreatedAt *string `json:"createdAt,omitempty"` + + // Label The label assigned to the address + Label *string `json:"label,omitempty"` + + // Network The network of the approved address. Network can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Network *string `json:"network,omitempty"` + + // Scope Will return the scope of the address as either "account" or "group" + Scope *string `json:"scope,omitempty"` + + // Status The status of the address that will return as "active", "pending-time" or "pending-mua". The remaining time is exactly 7 days after the initial request. "pending-mua" is for multi-user accounts and will require another administator or fund manager on the account to approve the address. + Status *string `json:"status,omitempty"` +} + +// ApprovedAddressMessage defines model for ApprovedAddressMessage. +type ApprovedAddressMessage struct { + // Message Status or confirmation message for the approved address request or removal. + Message *string `json:"message,omitempty"` + + // Result Result status (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// ApprovedAddressesResponse Response envelope containing the approved withdrawal addresses. +type ApprovedAddressesResponse struct { + // ApprovedAddresses Array of approved addresses on both the account and group level. + ApprovedAddresses *[]ApprovedAddress `json:"approvedAddresses,omitempty"` +} + +// Balance defines model for Balance. +type Balance struct { + // UnderscoreTimestamp Server-side monotonically increasing clock value as an ISO 8601 timestamp. Clients can use this value to detect and filter out stale responses that may occur due to load balancing or potential stale servers. + UnderscoreTimestamp *time.Time `json:"_timestamp,omitempty"` + + // Amount The confirmed balance for the currency (also referred to as `confirmedBalance`). For crypto withdrawals, this value is **not** reduced until the withdrawal has been confirmed on the blockchain. This delay protects against blockchain reorganizations. Use the `available` field instead if you need balances that immediately reflect holds. + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Available The amount available for trading. This value is reduced **immediately** when an order hold or withdrawal hold is placed, making it the recommended field for tracking real-time spendable balances. + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The amount available for withdrawal + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Currency The currency symbol + Currency *string `json:"currency,omitempty"` + + // PendingDeposit The amount pending deposit + PendingDeposit *openapi_types.DecimalNumber `json:"pendingDeposit,omitempty"` + + // PendingWithdrawal The amount pending withdrawal + PendingWithdrawal *openapi_types.DecimalNumber `json:"pendingWithdrawal,omitempty"` + Type *BalanceType `json:"type,omitempty"` +} + +// BalanceType defines model for Balance.Type. +type BalanceType string + +// CancelAllOrdersBySessionRequest defines model for CancelAllOrdersBySessionRequest. +type CancelAllOrdersBySessionRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/session" + Request string `json:"request"` +} + +// CancelAllOrdersRequest defines model for CancelAllOrdersRequest. +type CancelAllOrdersRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/all" + Request string `json:"request"` +} + +// CancelAllResult defines model for CancelAllResult. +type CancelAllResult struct { + // Details cancelledOrders/cancelRejects with IDs of both + Details *struct { + CancelRejects *[]int64 `json:"cancelRejects,omitempty"` + CancelledOrders *[]int64 `json:"cancelledOrders,omitempty"` + } `json:"details,omitempty"` + Result *string `json:"result,omitempty"` +} + +// CancelOrderRequest defines model for CancelOrderRequest. +type CancelOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order ID given by `/order/new` + OrderId uint64 `json:"order_id"` + + // Request The literal string "/v1/order/cancel" + Request string `json:"request"` +} + +// CancelOrderResponse defines model for CancelOrderResponse. +type CancelOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Reason *CancelOrderResponseReason `json:"reason,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *CancelOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *CancelOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// CancelOrderResponseReason defines model for CancelOrderResponse.Reason. +type CancelOrderResponseReason string + +// CancelOrderResponseSide defines model for CancelOrderResponse.Side. +type CancelOrderResponseSide string + +// CancelOrderResponseType defines model for CancelOrderResponse.Type. +type CancelOrderResponseType string + +// Candle defines model for Candle. +type Candle = []float64 + +// CandleResponse defines model for CandleResponse. +type CandleResponse = []Candle + +// ClearingOrder defines model for ClearingOrder. +type ClearingOrder struct { + // Amount The order amount + Amount *string `json:"amount,omitempty"` + + // ClearingId The clearing ID + ClearingId *string `json:"clearing_id,omitempty"` + + // IsConfirmed Whether the order is confirmed + IsConfirmed *bool `json:"is_confirmed,omitempty"` + + // Price The order price + Price *string `json:"price,omitempty"` + Side *ClearingOrderSide `json:"side,omitempty"` + + // Status The order status + Status *string `json:"status,omitempty"` + + // Symbol The trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms The timestamp in milliseconds + Timestampms *int64 `json:"timestampms,omitempty"` +} + +// ClearingOrderSide defines model for ClearingOrder.Side. +type ClearingOrderSide string + +// CustodyFeeTransfer defines model for CustodyFeeTransfer. +type CustodyFeeTransfer struct { + // Eid Custody fee event id + Eid *int64 `json:"eid,omitempty"` + + // EventType Custody fee event type + EventType *string `json:"eventType,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // TxTime Time of Custody fee record in milliseconds + TxTime *int64 `json:"txTime,omitempty"` +} + +// ErrorResponse defines model for ErrorResponse. +type ErrorResponse struct { + // Message Detailed error message + Message *string `json:"message,omitempty"` + + // Reason A short description + Reason *string `json:"reason,omitempty"` + + // Result Error + Result *string `json:"result,omitempty"` +} + +// FeeEstimateRequest defines model for FeeEstimateRequest. +type FeeEstimateRequest struct { + // Account The name of the account within the subaccount group. + Account string `json:"account"` + + // Address Standard string format of cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v1/withdraw/{currencyCodeLowerCase}/feeEstimate` where `:currencyCodeLowerCase` is replaced with the currency code of a supported crypto-currency, e.g. `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateResponse defines model for FeeEstimateResponse. +type FeeEstimateResponse struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated gas fee + Fee *string `json:"fee,omitempty"` + + // IsOverride Value that shows if an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total nunber of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals left to use + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeeEstimateV2Request defines model for FeeEstimateV2Request. +type FeeEstimateV2Request struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Address Standard string format of the destination cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Memo It would be present if applicable, it will be present for cosmos address. + Memo *string `json:"memo,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v2/withdraw/{network}/{ticker}/feeEstimate` where `{network}` is the blockchain network (e.g. `ethereum`, `bitcoin`, `solana`) and `{ticker}` is the currency code (e.g. `eth`, `btc`, `sol`). See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateV2Response defines model for FeeEstimateV2Response. +type FeeEstimateV2Response struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated withdrawal fee as a decimal amount + Fee *openapi_types.DecimalNumber `json:"fee,omitempty"` + + // IsOverride Whether an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total number of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals remaining + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeePromos defines model for FeePromos. +type FeePromos struct { + // Symbols Symbols that currently have fee promos + Symbols *[]string `json:"symbols,omitempty"` +} + +// FundingAmountResponse defines model for FundingAmountResponse. +type FundingAmountResponse struct { + // Amount The dollar amount for a Long 1 position held in the symbol for funding period (1 hour) + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // EstimatedFundingAmount The estimated dollar amount for a Long 1 position held in the symbol for next funding period (1 hour) + EstimatedFundingAmount *openapi_types.DecimalNumber `json:"estimatedFundingAmount,omitempty"` + + // FundingDateTime UTC date time in format `yyyy-MM-ddThh:mm:ss.SSSZ` format + FundingDateTime *string `json:"fundingDateTime,omitempty"` + + // FundingTimestampMilliSecs Current funding amount Epoc time. + FundingTimestampMilliSecs *int64 `json:"fundingTimestampMilliSecs,omitempty"` + + // NextFundingTimestamp Next funding amount Epoc time. + NextFundingTimestamp *int64 `json:"nextFundingTimestamp,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` +} + +// FundingPayment defines model for FundingPayment. +type FundingPayment struct { + // EventType Event type + EventType FundingPaymentEventType `json:"eventType"` + HourlyFundingTransfer FundingTransfer `json:"hourlyFundingTransfer"` +} + +// FundingPaymentEventType Event type +type FundingPaymentEventType string + +// FundingPaymentReportItem defines model for FundingPaymentReportItem. +type FundingPaymentReportItem struct { + // Action Credit or Debit + Action FundingPaymentReportItemAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType FundingPaymentReportItemEventType `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingPaymentReportItemAction Credit or Debit +type FundingPaymentReportItemAction string + +// FundingPaymentReportItemEventType Event type +type FundingPaymentReportItemEventType string + +// FundingTransfer defines model for FundingTransfer. +type FundingTransfer struct { + // Action Credit or Debit + Action FundingTransferAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType string `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingTransferAction Credit or Debit +type FundingTransferAction string + +// FxRate defines model for FxRate. +type FxRate struct { + // AsOf timestamp + AsOf *TimestampType `json:"asOf,omitempty"` + + // Benchmark The market for which the retrieved price applies to + Benchmark *string `json:"benchmark,omitempty"` + + // FxPair The requested currency pair + FxPair *string `json:"fxPair,omitempty"` + + // Provider The market data provider + Provider *string `json:"provider,omitempty"` + + // Rate The exchange rate + Rate *float64 `json:"rate,omitempty"` +} + +// Heartbeat defines model for Heartbeat. +type Heartbeat struct { + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce *Heartbeat_Nonce `json:"nonce,omitempty"` + + // Request The literal string `/v1/heartbeat` + Request *string `json:"request,omitempty"` +} + +// HeartbeatNonce0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `'1495127793'` | `POST` only | +// | string (milliseconds) | `'1495127793000'` | `POST` only | +type HeartbeatNonce0 = string + +// HeartbeatNonce1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type HeartbeatNonce1 = int64 + +// Heartbeat_Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Heartbeat_Nonce struct { + union json.RawMessage +} + +// InstantQuote defines model for InstantQuote. +type InstantQuote struct { + // DepositFee The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + DepositFee *string `json:"depositFee,omitempty"` + + // DepositFeeCurrency Currency in which `depositFee` is taken + DepositFeeCurrency *string `json:"depositFeeCurrency,omitempty"` + + // Fee The fee quantity to be taken for the order upon execution + Fee *string `json:"fee,omitempty"` + + // FeeCurrency The currency label for the order + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // MaxAgeMs Number of milliseconds until this quote price expires. Once expired, you will need to request a new quote + MaxAgeMs *int `json:"maxAgeMs,omitempty"` + + // Pair The symbol passed in the quote request + Pair *string `json:"pair,omitempty"` + + // Price The quoted price of the asset. This will not change when attempting execution + Price *string `json:"price,omitempty"` + + // PriceCurrency The currency in which the order is priced. Matches `CCY2` in the symbol + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // Quantity The quantity of the asset to be bought or sold + Quantity *string `json:"quantity,omitempty"` + + // QuantityCurrency The currency label for the `quantity` field. Matches `CCY1` in the symbol + QuantityCurrency *string `json:"quantityCurrency,omitempty"` + + // QuoteId Unique ID for the quote. This is used in the execution of the order + QuoteId *int64 `json:"quoteId,omitempty"` + + // Side Either "buy" or "sell" + Side *InstantQuoteSide `json:"side,omitempty"` + + // TotalSpend Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + TotalSpend *string `json:"totalSpend,omitempty"` + + // TotalSpendCurrency Currency of the `totalSpend` to be spent on the order + TotalSpendCurrency *string `json:"totalSpendCurrency,omitempty"` +} + +// InstantQuoteSide Either "buy" or "sell" +type InstantQuoteSide string + +// InterestRateInfo defines model for InterestRateInfo. +type InterestRateInfo struct { + // Interval The time interval for the rate (currently only "hour" is supported) + Interval InterestRateInfoInterval `json:"interval"` + + // Rate The interest rate as a decimal string + Rate string `json:"rate"` +} + +// InterestRateInfoInterval The time interval for the rate (currently only "hour" is supported) +type InterestRateInfoInterval string + +// LimitOrderResponse defines model for LimitOrderResponse. +type LimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *LimitOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *LimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// LimitOrderResponseSide defines model for LimitOrderResponse.Side. +type LimitOrderResponseSide string + +// LimitOrderResponseType defines model for LimitOrderResponse.Type. +type LimitOrderResponseType string + +// LiquidationRisk defines model for LiquidationRisk. +type LiquidationRisk struct { + // LiquidationPrice The estimated price at which liquidation would occur (optional, may not be present for all positions) + LiquidationPrice *MoneyAmount `json:"liquidationPrice,omitempty"` + + // LossPercentage The percentage loss from current value that would trigger liquidation, formatted as decimal (e.g., "0.1550" = 15.50%) + LossPercentage string `json:"lossPercentage"` +} + +// MarginAccountSummary defines model for MarginAccountSummary. +type MarginAccountSummary struct { + // AvailableCollateral The amount of collateral available for new positions or withdrawals + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased with available collateral + BuyingPower MoneyAmount `json:"buyingPower"` + + // InterestRate Current interest rate on borrowed amounts (only present if borrows exist) + InterestRate *InterestRateInfo `json:"interestRate,omitempty"` + + // Leverage The current leverage ratio (notionalValue / marginAssetValue) + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if positions exist) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account that can contribute to funding positions + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold with available collateral + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed across all currencies + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MarginInterestRate defines model for MarginInterestRate. +type MarginInterestRate struct { + // BorrowRate The hourly borrow rate as a decimal + BorrowRate string `json:"borrowRate"` + + // BorrowRateAnnual The annualized borrow rate (daily rate × 365) + BorrowRateAnnual string `json:"borrowRateAnnual"` + + // BorrowRateDaily The daily borrow rate (hourly rate × 24) + BorrowRateDaily string `json:"borrowRateDaily"` + + // Currency The currency code (e.g., "BTC", "ETH", "USD") + Currency string `json:"currency"` + + // LastUpdated Unix timestamp in milliseconds when the rate was last updated + LastUpdated int64 `json:"lastUpdated"` +} + +// MarginOrderPreview defines model for MarginOrderPreview. +type MarginOrderPreview struct { + // Postorder Margin risk statistics after the order would be executed + Postorder MarginRiskStats `json:"postorder"` + + // Preorder Margin risk statistics before the order would be executed + Preorder MarginRiskStats `json:"preorder"` +} + +// MarginRatesResponse defines model for MarginRatesResponse. +type MarginRatesResponse struct { + // Rates Array of interest rates for all borrowable currencies + Rates []MarginInterestRate `json:"rates"` +} + +// MarginResponse defines model for MarginResponse. +type MarginResponse struct { + // AvailableMargin The difference between the `margin_assets_value` and `initial_margin`. + AvailableMargin *string `json:"available_margin,omitempty"` + + // BuyingPower The amount of that product the account could purchase based on current `initial_margin` and `margin_assets_value`. + BuyingPower *string `json:"buying_power,omitempty"` + + // EstimatedLiquidationPrice The estimated price for the asset at which liquidation would occur. + EstimatedLiquidationPrice *string `json:"estimated_liquidation_price,omitempty"` + + // InitialMargin The $ amount that is being required by the accounts current positions and open orders. + InitialMargin *string `json:"initial_margin,omitempty"` + + // InitialMarginPositions The contribution to `initial_margin` from open positions. + InitialMarginPositions *string `json:"initial_margin_positions,omitempty"` + + // Leverage The ratio of Notional Value to Margin Assets Value. + Leverage *string `json:"leverage,omitempty"` + + // MarginAssetsValue The $ equivalent value of all the assets available in the current trading account that can contribute to funding a derivatives position. + MarginAssetsValue *string `json:"margin_assets_value,omitempty"` + + // MarginMaintenanceLimit The minimum amount of `margin_assets_value` required before the account is moved to liquidation status. + MarginMaintenanceLimit *string `json:"margin_maintenance_limit,omitempty"` + + // NotionalValue The $ value of the current position. + NotionalValue *string `json:"notional_value,omitempty"` + + // ReservedMargin The contribution to `initial_margin` from open orders. + ReservedMargin *string `json:"reserved_margin,omitempty"` + + // ReservedMarginBuys The contribution to `initial_margin` from open BUY orders. + ReservedMarginBuys *string `json:"reserved_margin_buys,omitempty"` + + // ReservedMarginSells The contribution to `initial_margin` from open SELL orders. + ReservedMarginSells *string `json:"reserved_margin_sells,omitempty"` + + // SellingPower The amount of that product the account could sell based on current `initial_margin` and `margin_assets_value`. + SellingPower *string `json:"selling_power,omitempty"` +} + +// MarginRiskStats defines model for MarginRiskStats. +type MarginRiskStats struct { + // AvailableCollateral The amount of collateral available for new positions + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased + BuyingPower MoneyAmount `json:"buyingPower"` + + // Leverage The leverage ratio + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if applicable) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MoneyAmount defines model for MoneyAmount. +type MoneyAmount struct { + // Currency The currency code (e.g., "USD", "BTC", "ETH") + Currency string `json:"currency"` + + // Value The amount in the specified currency + Value string `json:"value"` +} + +// MyTrade defines model for MyTrade. +type MyTrade struct { + Aggressor *bool `json:"aggressor,omitempty"` + Amount *string `json:"amount,omitempty"` + Break *MyTradeBreak `json:"break,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + FeeAmount *string `json:"fee_amount,omitempty"` + FeeCurrency *string `json:"fee_currency,omitempty"` + IsAuctionFill *bool `json:"is_auction_fill,omitempty"` + OrderId *string `json:"order_id,omitempty"` + Price *string `json:"price,omitempty"` + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *MyTradeType `json:"type,omitempty"` +} + +// MyTradeBreak defines model for MyTrade.Break. +type MyTradeBreak string + +// MyTradeType defines model for MyTrade.Type. +type MyTradeType string + +// MyTradesRequest defines model for MyTradesRequest. +type MyTradesRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // LimitTrades The maximum number of trades to return. Default is 50, max is 500. + LimitTrades *int `json:"limit_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) to retrieve trades for + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// NetworkAssets defines model for NetworkAssets. +type NetworkAssets struct { + // Assets Alphabetically sorted array of enabled asset/token codes available on this network. Assets include both exchange-tradable and custody-supported tokens. + Assets *[]string `json:"assets,omitempty"` + + // Network The blockchain network identifier. + Network *string `json:"network,omitempty"` +} + +// NetworkToken defines model for NetworkToken. +type NetworkToken struct { + // Network Array of supported blockchain networks for the token. Many tokens (especially stablecoins like USDC, USDT) are available on multiple networks. + // + // Supported networks include: `bitcoin`, `ethereum`, `solana`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + Network *[]string `json:"network,omitempty"` + + // Token The requested token identifier. + Token *string `json:"token,omitempty"` +} + +// NewOrderRequest defines model for NewOrderRequest. +type NewOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Amount Quoted decimal amount to purchase + Amount string `json:"amount"` + + // ClientOrderId *Recommended*. A [client-specified order id](/client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // MarginOrder Set to `true` to place this order on a margin account using borrowed funds. Defaults to `false`. Only available for margin-enabled accounts. See [Margin Trading](/margin/account-summary) for details. + MarginOrder *bool `json:"margin_order,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce int64 `json:"nonce"` + + // Options An optional array containing at most one supported order execution option. See Order execution options for details. + Options *[]NewOrderRequestOptions `json:"options,omitempty"` + + // Price Quoted decimal amount to spend per unit + Price string `json:"price"` + + // Request The literal string "/v1/order/new" + Request string `json:"request"` + Side NewOrderRequestSide `json:"side"` + + // StopPrice The price to trigger a stop-limit order. Only available for stop-limit orders. + StopPrice *string `json:"stop_price,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) for the new order + Symbol string `json:"symbol"` + + // Type The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. + Type NewOrderRequestType `json:"type"` +} + +// NewOrderRequestOptions defines model for NewOrderRequest.Options. +type NewOrderRequestOptions string + +// NewOrderRequestSide defines model for NewOrderRequest.Side. +type NewOrderRequestSide string + +// NewOrderRequestType The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. +type NewOrderRequestType string + +// Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Nonce struct { + union json.RawMessage +} + +// Nonce1 defines model for . +type Nonce1 = int64 + +// NotionalBalance defines model for NotionalBalance. +type NotionalBalance struct { + // Amount The current balance + Amount *string `json:"amount,omitempty"` + + // AmountNotional Amount, in notional + AmountNotional *string `json:"amountNotional,omitempty"` + + // Available The amount that is available to trade + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal The amount that is available to withdraw + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // AvailableForWithdrawalNotional AvailableForWithdrawal, in notional + AvailableForWithdrawalNotional *string `json:"availableForWithdrawalNotional,omitempty"` + + // AvailableNotional Available, in notional + AvailableNotional *string `json:"availableNotional,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` +} + +// NotionalVolume defines model for NotionalVolume. +type NotionalVolume struct { + ApiAuctionFeeBps *int `json:"api_auction_fee_bps,omitempty"` + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiNotional30dVolume *string `json:"api_notional_30d_volume,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Date *openapi_types.Date `json:"date,omitempty"` + FeeTier *struct { + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Tier *string `json:"tier,omitempty"` + } `json:"fee_tier,omitempty"` + FixAuctionFeeBps *int `json:"fix_auction_fee_bps,omitempty"` + FixMakerFeeBps *int `json:"fix_maker_fee_bps,omitempty"` + FixTakerFeeBps *int `json:"fix_taker_fee_bps,omitempty"` + LastUpdatedMs *int64 `json:"last_updated_ms,omitempty"` + Notional1dVolume *[]struct { + // Date UTC date in `yyyy-MM-dd` format + Date *string `json:"date,omitempty"` + + // NotionalVolume Notional volume value in USD for this single day + NotionalVolume *string `json:"notional_volume,omitempty"` + } `json:"notional_1d_volume,omitempty"` + Notional30dVolume *string `json:"notional_30d_volume,omitempty"` + WebAuctionFeeBps *int `json:"web_auction_fee_bps,omitempty"` + WebMakerFeeBps *int `json:"web_maker_fee_bps,omitempty"` + WebTakerFeeBps *int `json:"web_taker_fee_bps,omitempty"` +} + +// OpenPosition defines model for OpenPosition. +type OpenPosition struct { + // AverageCost The average price of the current position. + AverageCost *string `json:"average_cost,omitempty"` + + // InstrumentType The type of instrument. Either "spot" or "perp". + InstrumentType *string `json:"instrument_type,omitempty"` + + // MarkPrice The current Mark Price for the Asset or the position. + MarkPrice *string `json:"mark_price,omitempty"` + + // NotionalValue The value of position; calculated as (`quantity` * `mark_price`). Value will be negative for shorts. + NotionalValue *string `json:"notional_value,omitempty"` + + // Quantity The position size. Value will be negative for shorts. + Quantity *string `json:"quantity,omitempty"` + + // RealisedPnl The current P&L that has been realised from the position. + RealisedPnl *string `json:"realised_pnl,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) of the order. + Symbol *string `json:"symbol,omitempty"` + + // UnrealisedPnl Current Mark to Market value of the positions. + UnrealisedPnl *string `json:"unrealised_pnl,omitempty"` +} + +// Order defines model for Order. +type Order struct { + // AvgExecutionPrice The average price at which this order as been executed so far. 0 if the order has not been executed at all. + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + + // ClientOrderId An optional [client-specified order id](/client-order-id#client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // ExecutedAmount The amount of the order that has been filled. + ExecutedAmount *string `json:"executed_amount,omitempty"` + + // IsCancelled `true` if the order has been canceled. Note the spelling, "cancelled" instead of "canceled". This is for compatibility reasons. + IsCancelled *bool `json:"is_cancelled,omitempty"` + + // IsHidden Will always return `false`. + IsHidden *bool `json:"is_hidden,omitempty"` + + // IsLive `true` if the order is active on the book (has remaining quantity and has not been canceled) + IsLive *bool `json:"is_live,omitempty"` + + // Options An array containing at most one supported order execution option. See [Order execution options](/rest/orders#create-new-order) for details. + Options *[]string `json:"options,omitempty"` + + // OrderId The order id + OrderId *string `json:"order_id,omitempty"` + + // OriginalAmount The originally submitted amount of the order. + OriginalAmount *string `json:"original_amount,omitempty"` + + // Price The price the order was issued at + Price *string `json:"price,omitempty"` + + // Reason Populated with the reason your order was canceled, if available. + Reason *string `json:"reason,omitempty"` + + // RemainingAmount The amount of the order that has not been filled. + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *OrderSide `json:"side,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums#symbols-and-minimums) of the order + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Trades Contains an array of JSON objects with trade details. + Trades *[]struct { + // Aggressor If `true`, this order was the taker in the trade + Aggressor *bool `json:"aggressor,omitempty"` + + // Amount The quantity that was executed + Amount *string `json:"amount,omitempty"` + + // Break Will only be present if the trade is broken. See `Break Types` below for more information. + Break *string `json:"break,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The amount charged + FeeAmount *string `json:"fee_amount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"fee_currency,omitempty"` + + // OrderId The order that this trade executed against + OrderId *string `json:"order_id,omitempty"` + + // Price The price that the execution happened at + Price *string `json:"price,omitempty"` + + // Tid Unique identifier for the trade + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type Will be either "Buy" or "Sell", indicating the side of the original order + Type *OrderTradesType `json:"type,omitempty"` + } `json:"trades,omitempty"` + + // Type Description of the order + Type *OrderType `json:"type,omitempty"` + + // WasForced Will always be `false`. + WasForced *bool `json:"was_forced,omitempty"` +} + +// OrderSide defines model for Order.Side. +type OrderSide string + +// OrderTradesType Will be either "Buy" or "Sell", indicating the side of the original order +type OrderTradesType string + +// OrderType Description of the order +type OrderType string + +// OrderBook defines model for OrderBook. +type OrderBook struct { + // Asks The ask price levels currently on the book. These are offers to sell at a given price. + Asks *[]OrderBookEntry `json:"asks,omitempty"` + + // Bids The bid price levels currently on the book. These are offers to buy at a given price. + Bids *[]OrderBookEntry `json:"bids,omitempty"` +} + +// OrderBookEntry defines model for OrderBookEntry. +type OrderBookEntry struct { + // Amount The total quantity remaining at the price + Amount *string `json:"amount,omitempty"` + + // Price The price + Price *string `json:"price,omitempty"` + + // Timestamp **DO NOT USE** - this field is included for compatibility reasons only and is just populated with a dummy value. + Timestamp *string `json:"timestamp,omitempty"` +} + +// OrderStatusRequest defines model for OrderStatusRequest. +type OrderStatusRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // ClientOrderId The `client_order_id` used when placing the order. `client_order_id` cannot be used in combination with `order_id` + ClientOrderId *string `json:"client_order_id,omitempty"` + + // IncludeTrades Either `True` or `False`. If `True` the endpoint will return individual trade details of all fills from the order. + IncludeTrades *bool `json:"include_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order id to get information on. The `order_id` represents a whole number and is transmitted as an unsigned 64-bit integer in JSON format. `order_id` cannot be used in combination with `client_order_id`. + OrderId uint64 `json:"order_id"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// PaymentMethodBalance defines model for PaymentMethodBalance. +type PaymentMethodBalance struct { + // Amount Total account balance for currency. + Amount *string `json:"amount,omitempty"` + + // Available Total amount available for trading + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal Total amount available for withdrawal + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // Currency Symbol for fiat balance. + Currency *string `json:"currency,omitempty"` + + // Type Account type. Will always be `exchange` + Type *string `json:"type,omitempty"` +} + +// PaymentMethodBank defines model for PaymentMethodBank. +type PaymentMethodBank struct { + // Bank Name of bank account + Bank *string `json:"bank,omitempty"` + + // BankId Unique identifier for bank account + BankId *string `json:"bankId,omitempty"` +} + +// PaymentMethodsResponse defines model for PaymentMethodsResponse. +type PaymentMethodsResponse struct { + // Balances Array of JSON objects with available fiat currencies and their balances. + Balances *[]PaymentMethodBalance `json:"balances,omitempty"` + + // Banks Array of JSON objects with banking information + Banks *[]PaymentMethodBank `json:"banks,omitempty"` +} + +// PriceFeedResponse defines model for PriceFeedResponse. +type PriceFeedResponse = []struct { + // Pair Trading pair symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Pair *string `json:"pair,omitempty"` + + // PercentChange24h 24 hour change in price of the pair on the Gemini order book + PercentChange24h *string `json:"percentChange24h,omitempty"` + + // Price Current price of the pair on the Gemini order book + Price *string `json:"price,omitempty"` +} + +// Quantity defines model for Quantity. +type Quantity struct { + // Currency The currency code of the quantity. + Currency string `json:"currency"` + + // Value The value of the quantity. + Value string `json:"value"` +} + +// RevokeOauthTokenResponse defines model for RevokeOauthTokenResponse. +type RevokeOauthTokenResponse struct { + // Message A message that indicates the token has been revoked for the account + Message *string `json:"message,omitempty"` +} + +// RiskStatsResponse defines model for RiskStatsResponse. +type RiskStatsResponse struct { + // IndexPrice Current index price at the time of request + IndexPrice *string `json:"index_price,omitempty"` + + // MarkPrice Current mark price at the time of request + MarkPrice *string `json:"mark_price,omitempty"` + + // OpenInterest string representation of decimal value of open interest + OpenInterest *string `json:"open_interest,omitempty"` + + // OpenInterestNotional string representation of decimal value of open interest notional + OpenInterestNotional *string `json:"open_interest_notional,omitempty"` + + // ProductType Contract type for which the symbol data is fetched + ProductType *RiskStatsResponseProductType `json:"product_type,omitempty"` +} + +// RiskStatsResponseProductType Contract type for which the symbol data is fetched +type RiskStatsResponseProductType string + +// RoleResponse defines model for RoleResponse. +type RoleResponse struct { + // CounterpartyId _Only returned for master-level API keys_. The Gemini clearing counterparty ID associated with the API key making the request. + CounterpartyId *string `json:"counterparty_id,omitempty"` + + // IsAccountAdmin _Only returned for master-level API keys_.`True` if the Administrator role is assigned to the API keys. `False` otherwise. + IsAccountAdmin *bool `json:"isAccountAdmin,omitempty"` + + // IsAuditor `True` if the Auditor role is assigned to the API keys. `False` otherwise. + IsAuditor bool `json:"isAuditor"` + + // IsFundManager `True` if the Fund Manager role is assigned to the API keys. `False` otherwise. + IsFundManager bool `json:"isFundManager"` + + // IsTrader `True` if the Trader role is assigned to the API keys. `False` otherwise. + IsTrader bool `json:"isTrader"` +} + +// StakingBalance defines model for StakingBalance. +type StakingBalance struct { + // Available The amount that is available to trade + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The Staking amount that is available to redeem to exchange account + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Balance The current Staking balance + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + BalanceByProvider *map[string]struct { + // Balance The current Staking balance per providerId + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + } `json:"balanceByProvider,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` + + // Type Will always be "Staking" + Type *string `json:"type,omitempty"` +} + +// StakingDeposit defines model for StakingDeposit. +type StakingDeposit struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rates A JSON object including one or many rates. If more than one rate it would be an array of rates. + Rates *struct { + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *int `json:"rate,omitempty"` + } `json:"rates,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StakingHistory defines model for StakingHistory. +type StakingHistory struct { + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + Transactions *[]StakingTransaction `json:"transactions,omitempty"` +} + +// StakingRate defines model for StakingRate. +type StakingRate struct { + // ApyPct Staking interest APY (Expressed as a percentage derived from the rate and rounded to 1/10th of a percent.) + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // DepositUsdLimit Maximum new amount in USD notional of this crypto that can participate in Gemini Staking per account per month + DepositUsdLimit *int `json:"depositUsdLimit,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *openapi_types.DecimalNumber `json:"rate,omitempty"` + + // RatePct `rate` expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRateProvider Currency Symbol Keys +type StakingRateProvider struct { + CurrencySymbol *StakingRate `json:"currency_symbol,omitempty"` +} + +// StakingRateResponse Provider UUID Keys +type StakingRateResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRateProvider `json:"provider_uuid,omitempty"` +} + +// StakingRewardPeriod defines model for StakingRewardPeriod. +type StakingRewardPeriod struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // ApyPct Staking reward rate expressed as an APY at time of accrual. Interest on Staking balances compounds daily based on the simple rate which is available from `/v1/staking/rates/` + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // FirstAccrualAt Time of first accrual. In iso datetime with timezone format + FirstAccrualAt *string `json:"firstAccrualAt,omitempty"` + + // LastAccrualAt Time of last accrual. In iso datetime with timezone format + LastAccrualAt *string `json:"lastAccrualAt,omitempty"` + + // NumberOfAccruals Number of accruals in the specific aggregate, typically one per day. If the rate is adjusted, new accruals are added. + NumberOfAccruals *int `json:"numberOfAccruals,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePct Rate expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRewards defines model for StakingRewards. +type StakingRewards struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePeriods Array of JSON objects with period accrual information + RatePeriods *[]StakingRewardPeriod `json:"ratePeriods,omitempty"` +} + +// StakingRewardsProvider Currency Symbol Keys +type StakingRewardsProvider struct { + CurrencySymbol *StakingRewards `json:"currency_symbol,omitempty"` +} + +// StakingRewardsResponse Provider UUID Keys +type StakingRewardsResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRewardsProvider `json:"provider_uuid,omitempty"` +} + +// StakingTransaction defines model for StakingTransaction. +type StakingTransaction struct { + // Amount The amount that is defined by the transactionType above + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountCurrency Currency code + AmountCurrency *string `json:"amountCurrency,omitempty"` + + // DateTime timestamp + DateTime *TimestampType `json:"dateTime,omitempty"` + + // PriceAmount Current market price of the underlying token at the time of the reward + PriceAmount *openapi_types.DecimalNumber `json:"priceAmount,omitempty"` + + // PriceCurrency A supported three-letter fiat currency code, e.g. usd + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` + + // TransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment + TransactionType *StakingTransactionTransactionType `json:"transactionType,omitempty"` +} + +// StakingTransactionTransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment +type StakingTransactionTransactionType string + +// StakingWithdrawal defines model for StakingWithdrawal. +type StakingWithdrawal struct { + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountPaidSoFar The amount redeemed successfully + AmountPaidSoFar *openapi_types.DecimalNumber `json:"amountPaidSoFar,omitempty"` + + // AmountRemaining The amount pending to be redeemed + AmountRemaining *openapi_types.DecimalNumber `json:"amountRemaining,omitempty"` + + // Currency Currency code + Currency *string `json:"currency,omitempty"` + + // RequestInitiated In ISO datetime with timezone format + RequestInitiated *string `json:"requestInitiated,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StopLimitOrderResponse defines model for StopLimitOrderResponse. +type StopLimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Side *StopLimitOrderResponseSide `json:"side,omitempty"` + StopPrice *string `json:"stop_price,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *StopLimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// StopLimitOrderResponseSide defines model for StopLimitOrderResponse.Side. +type StopLimitOrderResponseSide string + +// StopLimitOrderResponseType defines model for StopLimitOrderResponse.Type. +type StopLimitOrderResponseType string + +// SymbolDetails defines model for SymbolDetails. +type SymbolDetails struct { + // BaseCurrency CCY1 or the top currency. (i.e `BTC` in `BTCUSD`) + BaseCurrency *string `json:"base_currency,omitempty"` + + // ContractPriceCurrency CCY2 or the quote currency for spot instrument (i.e. `USD` in `BTCUSD`) + // Or collateral currency of the contract in case of perpetual swap instrument. + ContractPriceCurrency *string `json:"contract_price_currency,omitempty"` + + // ContractType `vanilla` / `linear` / `inverse` where `vanilla` is for spot + // while `linear` is for perpetual swap and `inverse` is a special case perpetual swap where the perpetual contract will be settled in base currency. + ContractType *string `json:"contract_type,omitempty"` + + // MinOrderSize The minimum order size in `base_currency` units (i.e `0.00001`) + MinOrderSize *string `json:"min_order_size,omitempty"` + + // ProductType Instrument type `spot` / `swap` -- where `swap` signifies `perpetual swap`. + ProductType *string `json:"product_type,omitempty"` + + // QuoteCurrency CCY2 or the quote currency. (i.e `USD` in `BTCUSD`) + QuoteCurrency *string `json:"quote_currency,omitempty"` + + // QuoteIncrement The number of decimal places in the `quote_currency` (i.e `0.01`) + QuoteIncrement *openapi_types.DecimalNumber `json:"quote_increment,omitempty"` + + // Status Status of the current order book. Can be `open`, `closed`, `cancel_only`, `post_only`, `limit_only`. + Status *string `json:"status,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` + + // TickSize The number of decimal places in the `base_currency`. (i.e `1e-8`) + TickSize *openapi_types.DecimalNumber `json:"tick_size,omitempty"` + + // WrapEnabled When `True`, symbol can be wrapped using this endpoint: + // `POST https://api.gemini.com/v1/wrap/:symbol` + WrapEnabled *bool `json:"wrap_enabled,omitempty"` +} + +// Ticker defines model for Ticker. +type Ticker struct { + // Ask The lowest ask currently available + Ask *string `json:"ask,omitempty"` + + // Bid The highest bid currently available + Bid *string `json:"bid,omitempty"` + + // Last The price of the last executed trade + Last *string `json:"last,omitempty"` + + // Volume Information about the 24 hour volume on the exchange. See properties below + Volume *struct { + // PriceSymbol The volume denominated in the price currency + PriceSymbol *string `json:"price_symbol,omitempty"` + + // QuantitySymbol The volume denominated in the quantity currency + QuantitySymbol *string `json:"quantity_symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + } `json:"volume,omitempty"` +} + +// TickerInfo defines model for TickerInfo. +type TickerInfo struct { + // Ask Current best offer + Ask *string `json:"ask,omitempty"` + + // Bid Current best bid + Bid *string `json:"bid,omitempty"` + + // Changes Hourly prices descending for past 24 hours + Changes *[]string `json:"changes,omitempty"` + + // Close Close price (most recent trade) + Close *string `json:"close,omitempty"` + + // High High price from 24 hours ago + High *string `json:"high,omitempty"` + + // Low Low price from 24 hours ago + Low *string `json:"low,omitempty"` + + // Open Open price from 24 hours ago + Open *string `json:"open,omitempty"` + + // Symbol The trading pair symbol + Symbol *string `json:"symbol,omitempty"` +} + +// TimestampType timestamp +type TimestampType struct { + union json.RawMessage +} + +// TimestampType0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `1495127793` | `POST` only | +// | string (milliseconds) | `1495127793000` | `POST` only | +type TimestampType0 = string + +// TimestampType1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type TimestampType1 = int64 + +// Trade defines model for Trade. +type Trade struct { + // Amount The amount that was traded + Amount *string `json:"amount,omitempty"` + + // Broken Whether the trade was broken or not. Broken trades will not be displayed by default; use the `include_breaks` to display them. + Broken *bool `json:"broken,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // Price The price the trade was executed at + Price *string `json:"price,omitempty"` + + // Tid The trade ID number + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type - `buy` means that an ask was removed from the book by an incoming buy order. + // - `sell` means that a bid was removed from the book by an incoming sell order. + Type *TradeType `json:"type,omitempty"` +} + +// TradeType - `buy` means that an ask was removed from the book by an incoming buy order. +// - `sell` means that a bid was removed from the book by an incoming sell order. +type TradeType string + +// TradeVolume defines model for TradeVolume. +type TradeVolume struct { + BaseCurrency *string `json:"base_currency,omitempty"` + BuyMakerBase *string `json:"buy_maker_base,omitempty"` + BuyMakerCount *int `json:"buy_maker_count,omitempty"` + BuyMakerNotional *string `json:"buy_maker_notional,omitempty"` + BuyTakerBase *string `json:"buy_taker_base,omitempty"` + BuyTakerCount *int `json:"buy_taker_count,omitempty"` + BuyTakerNotional *string `json:"buy_taker_notional,omitempty"` + DataDate *string `json:"data_date,omitempty"` + MakerBuySellRatio *string `json:"maker_buy_sell_ratio,omitempty"` + NotionalCurrency *string `json:"notional_currency,omitempty"` + QuoteCurrency *string `json:"quote_currency,omitempty"` + SellMakerBase *string `json:"sell_maker_base,omitempty"` + SellMakerCount *int `json:"sell_maker_count,omitempty"` + SellMakerNotional *string `json:"sell_maker_notional,omitempty"` + SellTakerBase *string `json:"sell_taker_base,omitempty"` + SellTakerCount *int `json:"sell_taker_count,omitempty"` + SellTakerNotional *string `json:"sell_taker_notional,omitempty"` + Symbol *string `json:"symbol,omitempty"` + TotalVolumeBase *string `json:"total_volume_base,omitempty"` +} + +// Transaction defines model for Transaction. +type Transaction struct { + union json.RawMessage +} + +// Transaction0 Trade Reponse +type Transaction0 struct { + // Account The account. + Account *string `json:"account,omitempty"` + + // Amount The quantity that was executed. + Amount *string `json:"amount,omitempty"` + + // ClientOrderId The client order ID, if defined. Otherwise an empty string. + ClientOrderId *string `json:"clientOrderId,omitempty"` + + // Exchange Will always be "gemini". + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeAssetCode The symbol that the trade was for + FeeAssetCode *string `json:"feeAssetCode,omitempty"` + + // IsAggressor If true, this order was the taker in the trade. + IsAggressor *bool `json:"isAggressor,omitempty"` + + // IsAuctionFill True if the trade was a auction trade and not an on-exchange trade. + IsAuctionFill *bool `json:"isAuctionFill,omitempty"` + + // IsClearingFill True if the trade was a clearing trade and not an on-exchange trade. + IsClearingFill *bool `json:"isClearingFill,omitempty"` + + // OrderId The order that this trade executed against. + OrderId *int64 `json:"orderId,omitempty"` + + // Price The price that the execution happened at. + Price *string `json:"price,omitempty"` + + // Side Indicating the side of the original order. + Side *string `json:"side,omitempty"` + + // Symbol The symbol that the trade was for. + Symbol *string `json:"symbol,omitempty"` + + // Tid The trade ID. + Tid *int64 `json:"tid,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` +} + +// Transaction1 Transfer Reponse +type Transaction1 struct { + // AdvanceEid Deposit advance event ID. + AdvanceEid *int64 `json:"advanceEid,omitempty"` + + // Amount The quantity that was transferred. + Amount *string `json:"amount,omitempty"` + + // BankId Bank ID. + BankId *string `json:"bankId,omitempty"` + + // ClientTransferId Client Transfer ID. Client transfer ID is an optional client-supplied unique identifier for each withdrawal or internal transfer. + ClientTransferId *string `json:"clientTransferId,omitempty"` + + // CorrelationId Correlation ID. + CorrelationId *int64 `json:"correlationId,omitempty"` + + // Currency Currency code, see symbols + Currency *string `json:"currency,omitempty"` + + // Destination The account you are transferring to. + Destination *string `json:"destination,omitempty"` + + // Eid Transfer event id. + Eid *int64 `json:"eid,omitempty"` + + // FeeId Fee ID. + FeeId *string `json:"feeId,omitempty"` + + // Method Type of transfer method. + Method *string `json:"method,omitempty"` + + // OperationReason The operation reason. + OperationReason *string `json:"operationReason,omitempty"` + + // PendingEid Pending event ID. + PendingEid *int64 `json:"pendingEid,omitempty"` + + // Purpose Purpose. + Purpose *string `json:"purpose,omitempty"` + + // Source The account you are transferring from. + Source *string `json:"source,omitempty"` + + // Status The status of the transfer. + Status *string `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TransactionHash Supplies the transaction hash when available. + TransactionHash *string `json:"transactionHash,omitempty"` + + // TransferId Transfer ID. + TransferId *string `json:"transferId,omitempty"` + + // TransferType Transfer type. + TransferType *string `json:"transferType,omitempty"` + + // WithdrawalEid Withdrawal event ID. + WithdrawalEid *int64 `json:"withdrawalEid,omitempty"` + + // WithdrawalId Withdrawal ID. + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// Transfer defines model for Transfer. +type Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Eid The transfer ID + Eid *int64 `json:"eid,omitempty"` + Status *TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The transaction hash if applicable + TxHash *string `json:"txHash,omitempty"` + Type *TransferType `json:"type,omitempty"` +} + +// TransferStatus defines model for Transfer.Status. +type TransferStatus string + +// TransferType defines model for Transfer.Type. +type TransferType string + +// V2Transfer defines model for V2Transfer. +type V2Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Destination The destination address for withdrawals + Destination *string `json:"destination,omitempty"` + + // Eid The transfer event ID + Eid *int64 `json:"eid,omitempty"` + + // FeeAmount The fee charged for the transfer + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency The currency in which the fee was charged + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // Method The transfer method (e.g., `ACH`, `CreditCard`) + Method *string `json:"method,omitempty"` + + // Network The blockchain network the transfer was executed on (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`). Not present for fiat or administrative transfers. + Network *string `json:"network,omitempty"` + + // OutputIdx The output index for withdrawals + OutputIdx *int `json:"outputIdx,omitempty"` + + // Purpose The purpose or reason for administrative transfers + Purpose *string `json:"purpose,omitempty"` + + // Status The status of the transfer + Status *V2TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The on-chain transaction hash, if applicable + TxHash *string `json:"txHash,omitempty"` + + // Type The type of the transfer + Type *V2TransferType `json:"type,omitempty"` + + // WithdrawalId The unique withdrawal identifier + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// V2TransferStatus The status of the transfer +type V2TransferStatus string + +// V2TransferType The type of the transfer +type V2TransferType string + +// WithdrawCryptoFundsResponse Response returned after submitting a v2 cryptocurrency withdrawal. +type WithdrawCryptoFundsResponse struct { + // Address Standard string format of the withdrawal destination address + Address *string `json:"address,omitempty"` + + // Amount The withdrawal amount + Amount *string `json:"amount,omitempty"` + + // Currency The currency code of the withdrawn asset + Currency *string `json:"currency,omitempty"` + + // Fee The fee charged for the withdrawal + Fee *string `json:"fee,omitempty"` + + // WithdrawalId A unique ID for the withdrawal + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// ApiKeyAuth defines model for apiKeyAuth. +type ApiKeyAuth = string + +// CacheControl defines model for cacheControl. +type CacheControl = string + +// ContentLength defines model for contentLength. +type ContentLength = string + +// ContentType defines model for contentType. +type ContentType = string + +// CurrencyParam defines model for currencyParam. +type CurrencyParam = string + +// NetworkParam defines model for networkParam. +type NetworkParam = string + +// PayloadAuth defines model for payloadAuth. +type PayloadAuth = string + +// SignatureAuth defines model for signatureAuth. +type SignatureAuth = string + +// SymbolParam defines model for symbolParam. +type SymbolParam = string + +// TimestampParam timestamp +type TimestampParam = TimestampType + +// ApiKeyIpFilteringFailure defines model for ApiKeyIpFilteringFailure. +type ApiKeyIpFilteringFailure = ErrorResponse + +// BadRequest defines model for BadRequest. +type BadRequest = ErrorResponse + +// InternalError defines model for InternalError. +type InternalError = ErrorResponse + +// NotFound defines model for NotFound. +type NotFound = ErrorResponse + +// TooManyRequests defines model for TooManyRequests. +type TooManyRequests = ErrorResponse + +// Unauthorized defines model for Unauthorized. +type Unauthorized = ErrorResponse + +// apiKeyAuthContextKey is the context key for apiKeyAuth security scheme +type apiKeyAuthContextKey string + +// payloadAuthContextKey is the context key for payloadAuth security scheme +type payloadAuthContextKey string + +// signatureAuthContextKey is the context key for signatureAuth security scheme +type signatureAuthContextKey string + +// GetCurrentOrderBookParams defines parameters for GetCurrentOrderBook. +type GetCurrentOrderBookParams struct { + // LimitBids Limit the number of bid (offers to buy) price levels returned. Default is 50. May be 0 to return the full order book on this side. + LimitBids *float32 `form:"limit_bids,omitempty" json:"limit_bids,omitempty"` + + // LimitAsks Limit the number of ask (offers to sell) price levels returned. Default is 50. May be 0 to return the full order book on this side. + LimitAsks *float32 `form:"limit_asks,omitempty" json:"limit_asks,omitempty"` +} + +// GetFundingAmountReportFileParams defines parameters for GetFundingAmountReportFile. +type GetFundingAmountReportFileParams struct { + // Symbol Trading pair symbol

+ // + // `BTCGUSDPERP`, etc. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols). + Symbol string `form:"symbol" json:"symbol"` + + // FromDate Mandatory if `toDate` is specified, else optional. If empty, will only fetch records by numRows value. + FromDate *openapi_types.Date `form:"fromDate,omitempty" json:"fromDate,omitempty"` + + // ToDate Mandatory if `fromDate` is specified, else optional. If empty, will only fetch records by numRows value. + ToDate *openapi_types.Date `form:"toDate,omitempty" json:"toDate,omitempty"` + + // NumRows If empty, default value '8760' + NumRows *int `form:"numRows,omitempty" json:"numRows,omitempty"` +} + +// ListTradesParams defines parameters for ListTrades. +type ListTradesParams struct { + // Timestamp Only return trades after this timestamp. See [**Timestamps**](/rest/~schemas#timestamp-type) for more information. If not present, will show the most recent trades. For backwards compatibility, you may also use the alias `since`. With timestamp, there is a 90-day hard limit. + Timestamp *TimestampType `form:"timestamp,omitempty" json:"timestamp,omitempty"` + + // SinceTid Only retuns trades that executed after this tid. since_tid trumps timestamp parameter which has no effect if provided too. You may set since_tid to zero to get the earliest available trade history data. + SinceTid *int64 `form:"since_tid,omitempty" json:"since_tid,omitempty"` + + // LimitTrades The maximum number of trades to return. The default is 50. + LimitTrades *float32 `form:"limit_trades,omitempty" json:"limit_trades,omitempty"` + + // IncludeBreaks Whether to display broken trades. False by default. Can be `1` or `true` to activate + IncludeBreaks *bool `form:"include_breaks,omitempty" json:"include_breaks,omitempty"` +} + +// ListCandlesParamsTimeFrame defines parameters for ListCandles. +type ListCandlesParamsTimeFrame string + +// ListDerivativeCandlesParamsTimeFrame defines parameters for ListDerivativeCandles. +type ListDerivativeCandlesParamsTimeFrame string + +// GetFXRateParams defines parameters for GetFXRate. +type GetFXRateParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetTokenNetworkV2Params defines parameters for GetTokenNetworkV2. +type GetTokenNetworkV2Params struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetAssetsForNetworkParams defines parameters for GetAssetsForNetwork. +type GetAssetsForNetworkParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// AsHeartbeatNonce0 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce0 +func (t Heartbeat_Nonce) AsHeartbeatNonce0() (HeartbeatNonce0, error) { + var body HeartbeatNonce0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce0 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) FromHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce0 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsHeartbeatNonce1 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce1 +func (t Heartbeat_Nonce) AsHeartbeatNonce1() (HeartbeatNonce1, error) { + var body HeartbeatNonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce1 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) FromHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce1 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Heartbeat_Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Heartbeat_Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType returns the union data inside the Nonce as a TimestampType +func (t Nonce) AsTimestampType() (TimestampType, error) { + var body TimestampType + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType overwrites any union data inside the Nonce as the provided TimestampType +func (t *Nonce) FromTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType performs a merge with any union data inside the Nonce, using the provided TimestampType +func (t *Nonce) MergeTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNonce1 returns the union data inside the Nonce as a Nonce1 +func (t Nonce) AsNonce1() (Nonce1, error) { + var body Nonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNonce1 overwrites any union data inside the Nonce as the provided Nonce1 +func (t *Nonce) FromNonce1(v Nonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNonce1 performs a merge with any union data inside the Nonce, using the provided Nonce1 +func (t *Nonce) MergeNonce1(v Nonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType0 returns the union data inside the TimestampType as a TimestampType0 +func (t TimestampType) AsTimestampType0() (TimestampType0, error) { + var body TimestampType0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType0 overwrites any union data inside the TimestampType as the provided TimestampType0 +func (t *TimestampType) FromTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType0 performs a merge with any union data inside the TimestampType, using the provided TimestampType0 +func (t *TimestampType) MergeTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTimestampType1 returns the union data inside the TimestampType as a TimestampType1 +func (t TimestampType) AsTimestampType1() (TimestampType1, error) { + var body TimestampType1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType1 overwrites any union data inside the TimestampType as the provided TimestampType1 +func (t *TimestampType) FromTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType1 performs a merge with any union data inside the TimestampType, using the provided TimestampType1 +func (t *TimestampType) MergeTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t TimestampType) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *TimestampType) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTransaction0 returns the union data inside the Transaction as a Transaction0 +func (t Transaction) AsTransaction0() (Transaction0, error) { + var body Transaction0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction0 overwrites any union data inside the Transaction as the provided Transaction0 +func (t *Transaction) FromTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction0 performs a merge with any union data inside the Transaction, using the provided Transaction0 +func (t *Transaction) MergeTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTransaction1 returns the union data inside the Transaction as a Transaction1 +func (t Transaction) AsTransaction1() (Transaction1, error) { + var body Transaction1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction1 overwrites any union data inside the Transaction as the provided Transaction1 +func (t *Transaction) FromTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction1 performs a merge with any union data inside the Transaction, using the provided Transaction1 +func (t *Transaction) MergeTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Transaction) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Transaction) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/packages/sdk-go/generated/perpetuals/types.gen.go b/packages/sdk-go/generated/perpetuals/types.gen.go new file mode 100644 index 0000000..6216533 --- /dev/null +++ b/packages/sdk-go/generated/perpetuals/types.gen.go @@ -0,0 +1,2859 @@ +// Code generated from rest.yaml (Derivatives). DO NOT EDIT. + +// Package perpetuals provides primitives to interact with the openapi HTTP API. +// +// Code generated by oapi-codegen. DO NOT EDIT. +package perpetuals + +import ( + "encoding/json" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/internal/runtime" + openapi_types "github.com/gemini/developer-platform/packages/sdk-go/types" +) + +const ( + ApiKeyAuthScopes apiKeyAuthContextKey = "apiKeyAuth.Scopes" + PayloadAuthScopes payloadAuthContextKey = "payloadAuth.Scopes" + SignatureAuthScopes signatureAuthContextKey = "signatureAuth.Scopes" +) + +// Defines values for BalanceType. +const ( + Exchange BalanceType = "exchange" +) + +// Valid indicates whether the value is a known member of the BalanceType enum. +func (e BalanceType) Valid() bool { + switch e { + case Exchange: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseReason. +const ( + ExceedsPriceLimits CancelOrderResponseReason = "ExceedsPriceLimits" + FillOrKillWouldNotFill CancelOrderResponseReason = "FillOrKillWouldNotFill" + ImmediateOrCancelWouldPost CancelOrderResponseReason = "ImmediateOrCancelWouldPost" + MakerOrCancelWouldTake CancelOrderResponseReason = "MakerOrCancelWouldTake" + MarketClosed CancelOrderResponseReason = "MarketClosed" + Requested CancelOrderResponseReason = "Requested" + SelfCrossPrevented CancelOrderResponseReason = "SelfCrossPrevented" + TradingClosed CancelOrderResponseReason = "TradingClosed" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseReason enum. +func (e CancelOrderResponseReason) Valid() bool { + switch e { + case ExceedsPriceLimits: + return true + case FillOrKillWouldNotFill: + return true + case ImmediateOrCancelWouldPost: + return true + case MakerOrCancelWouldTake: + return true + case MarketClosed: + return true + case Requested: + return true + case SelfCrossPrevented: + return true + case TradingClosed: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseSide. +const ( + CancelOrderResponseSideBuy CancelOrderResponseSide = "buy" + CancelOrderResponseSideSell CancelOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseSide enum. +func (e CancelOrderResponseSide) Valid() bool { + switch e { + case CancelOrderResponseSideBuy: + return true + case CancelOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseType. +const ( + CancelOrderResponseTypeExchangeLimit CancelOrderResponseType = "exchange limit" + CancelOrderResponseTypeExchangeMarket CancelOrderResponseType = "exchange market" + CancelOrderResponseTypeExchangeStopLimit CancelOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseType enum. +func (e CancelOrderResponseType) Valid() bool { + switch e { + case CancelOrderResponseTypeExchangeLimit: + return true + case CancelOrderResponseTypeExchangeMarket: + return true + case CancelOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for ClearingOrderSide. +const ( + ClearingOrderSideBuy ClearingOrderSide = "buy" + ClearingOrderSideSell ClearingOrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the ClearingOrderSide enum. +func (e ClearingOrderSide) Valid() bool { + switch e { + case ClearingOrderSideBuy: + return true + case ClearingOrderSideSell: + return true + default: + return false + } +} + +// Defines values for FundingPaymentEventType. +const ( + FundingPaymentEventTypeHourlyFundingTransfer FundingPaymentEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentEventType enum. +func (e FundingPaymentEventType) Valid() bool { + switch e { + case FundingPaymentEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemAction. +const ( + FundingPaymentReportItemActionCredit FundingPaymentReportItemAction = "Credit" + FundingPaymentReportItemActionDebit FundingPaymentReportItemAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemAction enum. +func (e FundingPaymentReportItemAction) Valid() bool { + switch e { + case FundingPaymentReportItemActionCredit: + return true + case FundingPaymentReportItemActionDebit: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemEventType. +const ( + FundingPaymentReportItemEventTypeHourlyFundingTransfer FundingPaymentReportItemEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemEventType enum. +func (e FundingPaymentReportItemEventType) Valid() bool { + switch e { + case FundingPaymentReportItemEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingTransferAction. +const ( + FundingTransferActionCredit FundingTransferAction = "Credit" + FundingTransferActionDebit FundingTransferAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingTransferAction enum. +func (e FundingTransferAction) Valid() bool { + switch e { + case FundingTransferActionCredit: + return true + case FundingTransferActionDebit: + return true + default: + return false + } +} + +// Defines values for InstantQuoteSide. +const ( + InstantQuoteSideBuy InstantQuoteSide = "buy" + InstantQuoteSideSell InstantQuoteSide = "sell" +) + +// Valid indicates whether the value is a known member of the InstantQuoteSide enum. +func (e InstantQuoteSide) Valid() bool { + switch e { + case InstantQuoteSideBuy: + return true + case InstantQuoteSideSell: + return true + default: + return false + } +} + +// Defines values for InterestRateInfoInterval. +const ( + Hour InterestRateInfoInterval = "hour" +) + +// Valid indicates whether the value is a known member of the InterestRateInfoInterval enum. +func (e InterestRateInfoInterval) Valid() bool { + switch e { + case Hour: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseSide. +const ( + LimitOrderResponseSideBuy LimitOrderResponseSide = "buy" + LimitOrderResponseSideSell LimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseSide enum. +func (e LimitOrderResponseSide) Valid() bool { + switch e { + case LimitOrderResponseSideBuy: + return true + case LimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseType. +const ( + LimitOrderResponseTypeExchangeLimit LimitOrderResponseType = "exchange limit" + LimitOrderResponseTypeExchangeMarket LimitOrderResponseType = "exchange market" + LimitOrderResponseTypeExchangeStopLimit LimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseType enum. +func (e LimitOrderResponseType) Valid() bool { + switch e { + case LimitOrderResponseTypeExchangeLimit: + return true + case LimitOrderResponseTypeExchangeMarket: + return true + case LimitOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for MyTradeBreak. +const ( + Empty MyTradeBreak = "" + TradeCorrect MyTradeBreak = "trade correct" +) + +// Valid indicates whether the value is a known member of the MyTradeBreak enum. +func (e MyTradeBreak) Valid() bool { + switch e { + case Empty: + return true + case TradeCorrect: + return true + default: + return false + } +} + +// Defines values for MyTradeType. +const ( + MyTradeTypeBuy MyTradeType = "Buy" + MyTradeTypeSell MyTradeType = "Sell" +) + +// Valid indicates whether the value is a known member of the MyTradeType enum. +func (e MyTradeType) Valid() bool { + switch e { + case MyTradeTypeBuy: + return true + case MyTradeTypeSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestOptions. +const ( + FillOrKill NewOrderRequestOptions = "fill-or-kill" + ImmediateOrCancel NewOrderRequestOptions = "immediate-or-cancel" + MakerOrCancel NewOrderRequestOptions = "maker-or-cancel" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestOptions enum. +func (e NewOrderRequestOptions) Valid() bool { + switch e { + case FillOrKill: + return true + case ImmediateOrCancel: + return true + case MakerOrCancel: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestSide. +const ( + NewOrderRequestSideBuy NewOrderRequestSide = "buy" + NewOrderRequestSideSell NewOrderRequestSide = "sell" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestSide enum. +func (e NewOrderRequestSide) Valid() bool { + switch e { + case NewOrderRequestSideBuy: + return true + case NewOrderRequestSideSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestType. +const ( + NewOrderRequestTypeExchangeLimit NewOrderRequestType = "exchange limit" + NewOrderRequestTypeExchangeMarket NewOrderRequestType = "exchange market" + NewOrderRequestTypeExchangeStopLimit NewOrderRequestType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestType enum. +func (e NewOrderRequestType) Valid() bool { + switch e { + case NewOrderRequestTypeExchangeLimit: + return true + case NewOrderRequestTypeExchangeMarket: + return true + case NewOrderRequestTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for OrderSide. +const ( + OrderSideBuy OrderSide = "buy" + OrderSideSell OrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the OrderSide enum. +func (e OrderSide) Valid() bool { + switch e { + case OrderSideBuy: + return true + case OrderSideSell: + return true + default: + return false + } +} + +// Defines values for OrderTradesType. +const ( + OrderTradesTypeBuy OrderTradesType = "Buy" + OrderTradesTypeSell OrderTradesType = "Sell" +) + +// Valid indicates whether the value is a known member of the OrderTradesType enum. +func (e OrderTradesType) Valid() bool { + switch e { + case OrderTradesTypeBuy: + return true + case OrderTradesTypeSell: + return true + default: + return false + } +} + +// Defines values for OrderType. +const ( + OrderTypeExchangeLimit OrderType = "exchange limit" + OrderTypeExchangeMarket OrderType = "exchange market" + OrderTypeExchangeStopLimit OrderType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the OrderType enum. +func (e OrderType) Valid() bool { + switch e { + case OrderTypeExchangeLimit: + return true + case OrderTypeExchangeMarket: + return true + case OrderTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for RiskStatsResponseProductType. +const ( + PerpetualSwapContract RiskStatsResponseProductType = "PerpetualSwapContract" +) + +// Valid indicates whether the value is a known member of the RiskStatsResponseProductType enum. +func (e RiskStatsResponseProductType) Valid() bool { + switch e { + case PerpetualSwapContract: + return true + default: + return false + } +} + +// Defines values for StakingTransactionTransactionType. +const ( + StakingTransactionTransactionTypeAdminCreditAdjustment StakingTransactionTransactionType = "AdminCreditAdjustment" + StakingTransactionTransactionTypeAdminDebitAdjustment StakingTransactionTransactionType = "AdminDebitAdjustment" + StakingTransactionTransactionTypeAdminRedeem StakingTransactionTransactionType = "AdminRedeem" + StakingTransactionTransactionTypeDeposit StakingTransactionTransactionType = "Deposit" + StakingTransactionTransactionTypeInterest StakingTransactionTransactionType = "Interest" + StakingTransactionTransactionTypeRedeem StakingTransactionTransactionType = "Redeem" + StakingTransactionTransactionTypeRedeemPayment StakingTransactionTransactionType = "RedeemPayment" +) + +// Valid indicates whether the value is a known member of the StakingTransactionTransactionType enum. +func (e StakingTransactionTransactionType) Valid() bool { + switch e { + case StakingTransactionTransactionTypeAdminCreditAdjustment: + return true + case StakingTransactionTransactionTypeAdminDebitAdjustment: + return true + case StakingTransactionTransactionTypeAdminRedeem: + return true + case StakingTransactionTransactionTypeDeposit: + return true + case StakingTransactionTransactionTypeInterest: + return true + case StakingTransactionTransactionTypeRedeem: + return true + case StakingTransactionTransactionTypeRedeemPayment: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseSide. +const ( + StopLimitOrderResponseSideBuy StopLimitOrderResponseSide = "buy" + StopLimitOrderResponseSideSell StopLimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseSide enum. +func (e StopLimitOrderResponseSide) Valid() bool { + switch e { + case StopLimitOrderResponseSideBuy: + return true + case StopLimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseType. +const ( + ExchangeStopLimit StopLimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseType enum. +func (e StopLimitOrderResponseType) Valid() bool { + switch e { + case ExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for TradeType. +const ( + TradeTypeBuy TradeType = "buy" + TradeTypeSell TradeType = "sell" +) + +// Valid indicates whether the value is a known member of the TradeType enum. +func (e TradeType) Valid() bool { + switch e { + case TradeTypeBuy: + return true + case TradeTypeSell: + return true + default: + return false + } +} + +// Defines values for TransferStatus. +const ( + TransferStatusComplete TransferStatus = "Complete" + TransferStatusPending TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the TransferStatus enum. +func (e TransferStatus) Valid() bool { + switch e { + case TransferStatusComplete: + return true + case TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for TransferType. +const ( + TransferTypeDeposit TransferType = "Deposit" + TransferTypeWithdrawal TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the TransferType enum. +func (e TransferType) Valid() bool { + switch e { + case TransferTypeDeposit: + return true + case TransferTypeWithdrawal: + return true + default: + return false + } +} + +// Defines values for V2TransferStatus. +const ( + V2TransferStatusAdvanced V2TransferStatus = "Advanced" + V2TransferStatusComplete V2TransferStatus = "Complete" + V2TransferStatusPending V2TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the V2TransferStatus enum. +func (e V2TransferStatus) Valid() bool { + switch e { + case V2TransferStatusAdvanced: + return true + case V2TransferStatusComplete: + return true + case V2TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for V2TransferType. +const ( + AdminCredit V2TransferType = "AdminCredit" + AdminDebit V2TransferType = "AdminDebit" + Deposit V2TransferType = "Deposit" + Reward V2TransferType = "Reward" + Withdrawal V2TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the V2TransferType enum. +func (e V2TransferType) Valid() bool { + switch e { + case AdminCredit: + return true + case AdminDebit: + return true + case Deposit: + return true + case Reward: + return true + case Withdrawal: + return true + default: + return false + } +} + +// Account defines model for Account. +type Account struct { + // AccountId The account ID + AccountId *string `json:"account_id,omitempty"` + + // Created The creation date + Created *string `json:"created,omitempty"` + + // IsDefault Whether the account is the default account + IsDefault *bool `json:"is_default,omitempty"` + + // Name The account name + Name *string `json:"name,omitempty"` +} + +// AddBankResponse defines model for AddBankResponse. +type AddBankResponse struct { + // ReferenceId Reference ID for the new bank addition request. Once received, send in a wire from the requested bank account to verify it and enable withdrawals to that account. + ReferenceId *string `json:"referenceId,omitempty"` + + // Result Status result (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// Address defines model for Address. +type Address struct { + // Address String representation of the cryptocurrency address + Address *string `json:"address,omitempty"` + + // Label If you provided a label when creating the address, it will be echoed back here + Label *string `json:"label,omitempty"` + + // Memo It would be present if applicable, it will be present for cosmos address + Memo *string `json:"memo,omitempty"` + + // Network The blockchain network for the address + Network *string `json:"network,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ApprovedAddress defines model for ApprovedAddress. +type ApprovedAddress struct { + // Address The address on the approved address list. + Address *string `json:"address,omitempty"` + + // CreatedAt UTC timestamp in millisecond of when the address was created. + CreatedAt *string `json:"createdAt,omitempty"` + + // Label The label assigned to the address + Label *string `json:"label,omitempty"` + + // Network The network of the approved address. Network can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Network *string `json:"network,omitempty"` + + // Scope Will return the scope of the address as either "account" or "group" + Scope *string `json:"scope,omitempty"` + + // Status The status of the address that will return as "active", "pending-time" or "pending-mua". The remaining time is exactly 7 days after the initial request. "pending-mua" is for multi-user accounts and will require another administator or fund manager on the account to approve the address. + Status *string `json:"status,omitempty"` +} + +// ApprovedAddressMessage defines model for ApprovedAddressMessage. +type ApprovedAddressMessage struct { + // Message Status or confirmation message for the approved address request or removal. + Message *string `json:"message,omitempty"` + + // Result Result status (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// ApprovedAddressesResponse Response envelope containing the approved withdrawal addresses. +type ApprovedAddressesResponse struct { + // ApprovedAddresses Array of approved addresses on both the account and group level. + ApprovedAddresses *[]ApprovedAddress `json:"approvedAddresses,omitempty"` +} + +// Balance defines model for Balance. +type Balance struct { + // UnderscoreTimestamp Server-side monotonically increasing clock value as an ISO 8601 timestamp. Clients can use this value to detect and filter out stale responses that may occur due to load balancing or potential stale servers. + UnderscoreTimestamp *time.Time `json:"_timestamp,omitempty"` + + // Amount The confirmed balance for the currency (also referred to as `confirmedBalance`). For crypto withdrawals, this value is **not** reduced until the withdrawal has been confirmed on the blockchain. This delay protects against blockchain reorganizations. Use the `available` field instead if you need balances that immediately reflect holds. + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Available The amount available for trading. This value is reduced **immediately** when an order hold or withdrawal hold is placed, making it the recommended field for tracking real-time spendable balances. + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The amount available for withdrawal + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Currency The currency symbol + Currency *string `json:"currency,omitempty"` + + // PendingDeposit The amount pending deposit + PendingDeposit *openapi_types.DecimalNumber `json:"pendingDeposit,omitempty"` + + // PendingWithdrawal The amount pending withdrawal + PendingWithdrawal *openapi_types.DecimalNumber `json:"pendingWithdrawal,omitempty"` + Type *BalanceType `json:"type,omitempty"` +} + +// BalanceType defines model for Balance.Type. +type BalanceType string + +// CancelAllOrdersBySessionRequest defines model for CancelAllOrdersBySessionRequest. +type CancelAllOrdersBySessionRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/session" + Request string `json:"request"` +} + +// CancelAllOrdersRequest defines model for CancelAllOrdersRequest. +type CancelAllOrdersRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/all" + Request string `json:"request"` +} + +// CancelAllResult defines model for CancelAllResult. +type CancelAllResult struct { + // Details cancelledOrders/cancelRejects with IDs of both + Details *struct { + CancelRejects *[]int64 `json:"cancelRejects,omitempty"` + CancelledOrders *[]int64 `json:"cancelledOrders,omitempty"` + } `json:"details,omitempty"` + Result *string `json:"result,omitempty"` +} + +// CancelOrderRequest defines model for CancelOrderRequest. +type CancelOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order ID given by `/order/new` + OrderId uint64 `json:"order_id"` + + // Request The literal string "/v1/order/cancel" + Request string `json:"request"` +} + +// CancelOrderResponse defines model for CancelOrderResponse. +type CancelOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Reason *CancelOrderResponseReason `json:"reason,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *CancelOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *CancelOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// CancelOrderResponseReason defines model for CancelOrderResponse.Reason. +type CancelOrderResponseReason string + +// CancelOrderResponseSide defines model for CancelOrderResponse.Side. +type CancelOrderResponseSide string + +// CancelOrderResponseType defines model for CancelOrderResponse.Type. +type CancelOrderResponseType string + +// Candle defines model for Candle. +type Candle = []float64 + +// CandleResponse defines model for CandleResponse. +type CandleResponse = []Candle + +// ClearingOrder defines model for ClearingOrder. +type ClearingOrder struct { + // Amount The order amount + Amount *string `json:"amount,omitempty"` + + // ClearingId The clearing ID + ClearingId *string `json:"clearing_id,omitempty"` + + // IsConfirmed Whether the order is confirmed + IsConfirmed *bool `json:"is_confirmed,omitempty"` + + // Price The order price + Price *string `json:"price,omitempty"` + Side *ClearingOrderSide `json:"side,omitempty"` + + // Status The order status + Status *string `json:"status,omitempty"` + + // Symbol The trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms The timestamp in milliseconds + Timestampms *int64 `json:"timestampms,omitempty"` +} + +// ClearingOrderSide defines model for ClearingOrder.Side. +type ClearingOrderSide string + +// CustodyFeeTransfer defines model for CustodyFeeTransfer. +type CustodyFeeTransfer struct { + // Eid Custody fee event id + Eid *int64 `json:"eid,omitempty"` + + // EventType Custody fee event type + EventType *string `json:"eventType,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // TxTime Time of Custody fee record in milliseconds + TxTime *int64 `json:"txTime,omitempty"` +} + +// ErrorResponse defines model for ErrorResponse. +type ErrorResponse struct { + // Message Detailed error message + Message *string `json:"message,omitempty"` + + // Reason A short description + Reason *string `json:"reason,omitempty"` + + // Result Error + Result *string `json:"result,omitempty"` +} + +// FeeEstimateRequest defines model for FeeEstimateRequest. +type FeeEstimateRequest struct { + // Account The name of the account within the subaccount group. + Account string `json:"account"` + + // Address Standard string format of cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v1/withdraw/{currencyCodeLowerCase}/feeEstimate` where `:currencyCodeLowerCase` is replaced with the currency code of a supported crypto-currency, e.g. `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateResponse defines model for FeeEstimateResponse. +type FeeEstimateResponse struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated gas fee + Fee *string `json:"fee,omitempty"` + + // IsOverride Value that shows if an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total nunber of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals left to use + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeeEstimateV2Request defines model for FeeEstimateV2Request. +type FeeEstimateV2Request struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Address Standard string format of the destination cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Memo It would be present if applicable, it will be present for cosmos address. + Memo *string `json:"memo,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v2/withdraw/{network}/{ticker}/feeEstimate` where `{network}` is the blockchain network (e.g. `ethereum`, `bitcoin`, `solana`) and `{ticker}` is the currency code (e.g. `eth`, `btc`, `sol`). See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateV2Response defines model for FeeEstimateV2Response. +type FeeEstimateV2Response struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated withdrawal fee as a decimal amount + Fee *openapi_types.DecimalNumber `json:"fee,omitempty"` + + // IsOverride Whether an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total number of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals remaining + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeePromos defines model for FeePromos. +type FeePromos struct { + // Symbols Symbols that currently have fee promos + Symbols *[]string `json:"symbols,omitempty"` +} + +// FundingAmountResponse defines model for FundingAmountResponse. +type FundingAmountResponse struct { + // Amount The dollar amount for a Long 1 position held in the symbol for funding period (1 hour) + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // EstimatedFundingAmount The estimated dollar amount for a Long 1 position held in the symbol for next funding period (1 hour) + EstimatedFundingAmount *openapi_types.DecimalNumber `json:"estimatedFundingAmount,omitempty"` + + // FundingDateTime UTC date time in format `yyyy-MM-ddThh:mm:ss.SSSZ` format + FundingDateTime *string `json:"fundingDateTime,omitempty"` + + // FundingTimestampMilliSecs Current funding amount Epoc time. + FundingTimestampMilliSecs *int64 `json:"fundingTimestampMilliSecs,omitempty"` + + // NextFundingTimestamp Next funding amount Epoc time. + NextFundingTimestamp *int64 `json:"nextFundingTimestamp,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` +} + +// FundingPayment defines model for FundingPayment. +type FundingPayment struct { + // EventType Event type + EventType FundingPaymentEventType `json:"eventType"` + HourlyFundingTransfer FundingTransfer `json:"hourlyFundingTransfer"` +} + +// FundingPaymentEventType Event type +type FundingPaymentEventType string + +// FundingPaymentReportItem defines model for FundingPaymentReportItem. +type FundingPaymentReportItem struct { + // Action Credit or Debit + Action FundingPaymentReportItemAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType FundingPaymentReportItemEventType `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingPaymentReportItemAction Credit or Debit +type FundingPaymentReportItemAction string + +// FundingPaymentReportItemEventType Event type +type FundingPaymentReportItemEventType string + +// FundingTransfer defines model for FundingTransfer. +type FundingTransfer struct { + // Action Credit or Debit + Action FundingTransferAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType string `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingTransferAction Credit or Debit +type FundingTransferAction string + +// FxRate defines model for FxRate. +type FxRate struct { + // AsOf timestamp + AsOf *TimestampType `json:"asOf,omitempty"` + + // Benchmark The market for which the retrieved price applies to + Benchmark *string `json:"benchmark,omitempty"` + + // FxPair The requested currency pair + FxPair *string `json:"fxPair,omitempty"` + + // Provider The market data provider + Provider *string `json:"provider,omitempty"` + + // Rate The exchange rate + Rate *float64 `json:"rate,omitempty"` +} + +// Heartbeat defines model for Heartbeat. +type Heartbeat struct { + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce *Heartbeat_Nonce `json:"nonce,omitempty"` + + // Request The literal string `/v1/heartbeat` + Request *string `json:"request,omitempty"` +} + +// HeartbeatNonce0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `'1495127793'` | `POST` only | +// | string (milliseconds) | `'1495127793000'` | `POST` only | +type HeartbeatNonce0 = string + +// HeartbeatNonce1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type HeartbeatNonce1 = int64 + +// Heartbeat_Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Heartbeat_Nonce struct { + union json.RawMessage +} + +// InstantQuote defines model for InstantQuote. +type InstantQuote struct { + // DepositFee The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + DepositFee *string `json:"depositFee,omitempty"` + + // DepositFeeCurrency Currency in which `depositFee` is taken + DepositFeeCurrency *string `json:"depositFeeCurrency,omitempty"` + + // Fee The fee quantity to be taken for the order upon execution + Fee *string `json:"fee,omitempty"` + + // FeeCurrency The currency label for the order + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // MaxAgeMs Number of milliseconds until this quote price expires. Once expired, you will need to request a new quote + MaxAgeMs *int `json:"maxAgeMs,omitempty"` + + // Pair The symbol passed in the quote request + Pair *string `json:"pair,omitempty"` + + // Price The quoted price of the asset. This will not change when attempting execution + Price *string `json:"price,omitempty"` + + // PriceCurrency The currency in which the order is priced. Matches `CCY2` in the symbol + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // Quantity The quantity of the asset to be bought or sold + Quantity *string `json:"quantity,omitempty"` + + // QuantityCurrency The currency label for the `quantity` field. Matches `CCY1` in the symbol + QuantityCurrency *string `json:"quantityCurrency,omitempty"` + + // QuoteId Unique ID for the quote. This is used in the execution of the order + QuoteId *int64 `json:"quoteId,omitempty"` + + // Side Either "buy" or "sell" + Side *InstantQuoteSide `json:"side,omitempty"` + + // TotalSpend Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + TotalSpend *string `json:"totalSpend,omitempty"` + + // TotalSpendCurrency Currency of the `totalSpend` to be spent on the order + TotalSpendCurrency *string `json:"totalSpendCurrency,omitempty"` +} + +// InstantQuoteSide Either "buy" or "sell" +type InstantQuoteSide string + +// InterestRateInfo defines model for InterestRateInfo. +type InterestRateInfo struct { + // Interval The time interval for the rate (currently only "hour" is supported) + Interval InterestRateInfoInterval `json:"interval"` + + // Rate The interest rate as a decimal string + Rate string `json:"rate"` +} + +// InterestRateInfoInterval The time interval for the rate (currently only "hour" is supported) +type InterestRateInfoInterval string + +// LimitOrderResponse defines model for LimitOrderResponse. +type LimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *LimitOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *LimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// LimitOrderResponseSide defines model for LimitOrderResponse.Side. +type LimitOrderResponseSide string + +// LimitOrderResponseType defines model for LimitOrderResponse.Type. +type LimitOrderResponseType string + +// LiquidationRisk defines model for LiquidationRisk. +type LiquidationRisk struct { + // LiquidationPrice The estimated price at which liquidation would occur (optional, may not be present for all positions) + LiquidationPrice *MoneyAmount `json:"liquidationPrice,omitempty"` + + // LossPercentage The percentage loss from current value that would trigger liquidation, formatted as decimal (e.g., "0.1550" = 15.50%) + LossPercentage string `json:"lossPercentage"` +} + +// MarginAccountSummary defines model for MarginAccountSummary. +type MarginAccountSummary struct { + // AvailableCollateral The amount of collateral available for new positions or withdrawals + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased with available collateral + BuyingPower MoneyAmount `json:"buyingPower"` + + // InterestRate Current interest rate on borrowed amounts (only present if borrows exist) + InterestRate *InterestRateInfo `json:"interestRate,omitempty"` + + // Leverage The current leverage ratio (notionalValue / marginAssetValue) + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if positions exist) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account that can contribute to funding positions + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold with available collateral + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed across all currencies + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MarginInterestRate defines model for MarginInterestRate. +type MarginInterestRate struct { + // BorrowRate The hourly borrow rate as a decimal + BorrowRate string `json:"borrowRate"` + + // BorrowRateAnnual The annualized borrow rate (daily rate × 365) + BorrowRateAnnual string `json:"borrowRateAnnual"` + + // BorrowRateDaily The daily borrow rate (hourly rate × 24) + BorrowRateDaily string `json:"borrowRateDaily"` + + // Currency The currency code (e.g., "BTC", "ETH", "USD") + Currency string `json:"currency"` + + // LastUpdated Unix timestamp in milliseconds when the rate was last updated + LastUpdated int64 `json:"lastUpdated"` +} + +// MarginOrderPreview defines model for MarginOrderPreview. +type MarginOrderPreview struct { + // Postorder Margin risk statistics after the order would be executed + Postorder MarginRiskStats `json:"postorder"` + + // Preorder Margin risk statistics before the order would be executed + Preorder MarginRiskStats `json:"preorder"` +} + +// MarginRatesResponse defines model for MarginRatesResponse. +type MarginRatesResponse struct { + // Rates Array of interest rates for all borrowable currencies + Rates []MarginInterestRate `json:"rates"` +} + +// MarginResponse defines model for MarginResponse. +type MarginResponse struct { + // AvailableMargin The difference between the `margin_assets_value` and `initial_margin`. + AvailableMargin *string `json:"available_margin,omitempty"` + + // BuyingPower The amount of that product the account could purchase based on current `initial_margin` and `margin_assets_value`. + BuyingPower *string `json:"buying_power,omitempty"` + + // EstimatedLiquidationPrice The estimated price for the asset at which liquidation would occur. + EstimatedLiquidationPrice *string `json:"estimated_liquidation_price,omitempty"` + + // InitialMargin The $ amount that is being required by the accounts current positions and open orders. + InitialMargin *string `json:"initial_margin,omitempty"` + + // InitialMarginPositions The contribution to `initial_margin` from open positions. + InitialMarginPositions *string `json:"initial_margin_positions,omitempty"` + + // Leverage The ratio of Notional Value to Margin Assets Value. + Leverage *string `json:"leverage,omitempty"` + + // MarginAssetsValue The $ equivalent value of all the assets available in the current trading account that can contribute to funding a derivatives position. + MarginAssetsValue *string `json:"margin_assets_value,omitempty"` + + // MarginMaintenanceLimit The minimum amount of `margin_assets_value` required before the account is moved to liquidation status. + MarginMaintenanceLimit *string `json:"margin_maintenance_limit,omitempty"` + + // NotionalValue The $ value of the current position. + NotionalValue *string `json:"notional_value,omitempty"` + + // ReservedMargin The contribution to `initial_margin` from open orders. + ReservedMargin *string `json:"reserved_margin,omitempty"` + + // ReservedMarginBuys The contribution to `initial_margin` from open BUY orders. + ReservedMarginBuys *string `json:"reserved_margin_buys,omitempty"` + + // ReservedMarginSells The contribution to `initial_margin` from open SELL orders. + ReservedMarginSells *string `json:"reserved_margin_sells,omitempty"` + + // SellingPower The amount of that product the account could sell based on current `initial_margin` and `margin_assets_value`. + SellingPower *string `json:"selling_power,omitempty"` +} + +// MarginRiskStats defines model for MarginRiskStats. +type MarginRiskStats struct { + // AvailableCollateral The amount of collateral available for new positions + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased + BuyingPower MoneyAmount `json:"buyingPower"` + + // Leverage The leverage ratio + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if applicable) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MoneyAmount defines model for MoneyAmount. +type MoneyAmount struct { + // Currency The currency code (e.g., "USD", "BTC", "ETH") + Currency string `json:"currency"` + + // Value The amount in the specified currency + Value string `json:"value"` +} + +// MyTrade defines model for MyTrade. +type MyTrade struct { + Aggressor *bool `json:"aggressor,omitempty"` + Amount *string `json:"amount,omitempty"` + Break *MyTradeBreak `json:"break,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + FeeAmount *string `json:"fee_amount,omitempty"` + FeeCurrency *string `json:"fee_currency,omitempty"` + IsAuctionFill *bool `json:"is_auction_fill,omitempty"` + OrderId *string `json:"order_id,omitempty"` + Price *string `json:"price,omitempty"` + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *MyTradeType `json:"type,omitempty"` +} + +// MyTradeBreak defines model for MyTrade.Break. +type MyTradeBreak string + +// MyTradeType defines model for MyTrade.Type. +type MyTradeType string + +// MyTradesRequest defines model for MyTradesRequest. +type MyTradesRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // LimitTrades The maximum number of trades to return. Default is 50, max is 500. + LimitTrades *int `json:"limit_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) to retrieve trades for + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// NetworkAssets defines model for NetworkAssets. +type NetworkAssets struct { + // Assets Alphabetically sorted array of enabled asset/token codes available on this network. Assets include both exchange-tradable and custody-supported tokens. + Assets *[]string `json:"assets,omitempty"` + + // Network The blockchain network identifier. + Network *string `json:"network,omitempty"` +} + +// NetworkToken defines model for NetworkToken. +type NetworkToken struct { + // Network Array of supported blockchain networks for the token. Many tokens (especially stablecoins like USDC, USDT) are available on multiple networks. + // + // Supported networks include: `bitcoin`, `ethereum`, `solana`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + Network *[]string `json:"network,omitempty"` + + // Token The requested token identifier. + Token *string `json:"token,omitempty"` +} + +// NewOrderRequest defines model for NewOrderRequest. +type NewOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Amount Quoted decimal amount to purchase + Amount string `json:"amount"` + + // ClientOrderId *Recommended*. A [client-specified order id](/client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // MarginOrder Set to `true` to place this order on a margin account using borrowed funds. Defaults to `false`. Only available for margin-enabled accounts. See [Margin Trading](/margin/account-summary) for details. + MarginOrder *bool `json:"margin_order,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce int64 `json:"nonce"` + + // Options An optional array containing at most one supported order execution option. See Order execution options for details. + Options *[]NewOrderRequestOptions `json:"options,omitempty"` + + // Price Quoted decimal amount to spend per unit + Price string `json:"price"` + + // Request The literal string "/v1/order/new" + Request string `json:"request"` + Side NewOrderRequestSide `json:"side"` + + // StopPrice The price to trigger a stop-limit order. Only available for stop-limit orders. + StopPrice *string `json:"stop_price,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) for the new order + Symbol string `json:"symbol"` + + // Type The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. + Type NewOrderRequestType `json:"type"` +} + +// NewOrderRequestOptions defines model for NewOrderRequest.Options. +type NewOrderRequestOptions string + +// NewOrderRequestSide defines model for NewOrderRequest.Side. +type NewOrderRequestSide string + +// NewOrderRequestType The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. +type NewOrderRequestType string + +// Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Nonce struct { + union json.RawMessage +} + +// Nonce1 defines model for . +type Nonce1 = int64 + +// NotionalBalance defines model for NotionalBalance. +type NotionalBalance struct { + // Amount The current balance + Amount *string `json:"amount,omitempty"` + + // AmountNotional Amount, in notional + AmountNotional *string `json:"amountNotional,omitempty"` + + // Available The amount that is available to trade + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal The amount that is available to withdraw + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // AvailableForWithdrawalNotional AvailableForWithdrawal, in notional + AvailableForWithdrawalNotional *string `json:"availableForWithdrawalNotional,omitempty"` + + // AvailableNotional Available, in notional + AvailableNotional *string `json:"availableNotional,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` +} + +// NotionalVolume defines model for NotionalVolume. +type NotionalVolume struct { + ApiAuctionFeeBps *int `json:"api_auction_fee_bps,omitempty"` + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiNotional30dVolume *string `json:"api_notional_30d_volume,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Date *openapi_types.Date `json:"date,omitempty"` + FeeTier *struct { + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Tier *string `json:"tier,omitempty"` + } `json:"fee_tier,omitempty"` + FixAuctionFeeBps *int `json:"fix_auction_fee_bps,omitempty"` + FixMakerFeeBps *int `json:"fix_maker_fee_bps,omitempty"` + FixTakerFeeBps *int `json:"fix_taker_fee_bps,omitempty"` + LastUpdatedMs *int64 `json:"last_updated_ms,omitempty"` + Notional1dVolume *[]struct { + // Date UTC date in `yyyy-MM-dd` format + Date *string `json:"date,omitempty"` + + // NotionalVolume Notional volume value in USD for this single day + NotionalVolume *string `json:"notional_volume,omitempty"` + } `json:"notional_1d_volume,omitempty"` + Notional30dVolume *string `json:"notional_30d_volume,omitempty"` + WebAuctionFeeBps *int `json:"web_auction_fee_bps,omitempty"` + WebMakerFeeBps *int `json:"web_maker_fee_bps,omitempty"` + WebTakerFeeBps *int `json:"web_taker_fee_bps,omitempty"` +} + +// OpenPosition defines model for OpenPosition. +type OpenPosition struct { + // AverageCost The average price of the current position. + AverageCost *string `json:"average_cost,omitempty"` + + // InstrumentType The type of instrument. Either "spot" or "perp". + InstrumentType *string `json:"instrument_type,omitempty"` + + // MarkPrice The current Mark Price for the Asset or the position. + MarkPrice *string `json:"mark_price,omitempty"` + + // NotionalValue The value of position; calculated as (`quantity` * `mark_price`). Value will be negative for shorts. + NotionalValue *string `json:"notional_value,omitempty"` + + // Quantity The position size. Value will be negative for shorts. + Quantity *string `json:"quantity,omitempty"` + + // RealisedPnl The current P&L that has been realised from the position. + RealisedPnl *string `json:"realised_pnl,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) of the order. + Symbol *string `json:"symbol,omitempty"` + + // UnrealisedPnl Current Mark to Market value of the positions. + UnrealisedPnl *string `json:"unrealised_pnl,omitempty"` +} + +// Order defines model for Order. +type Order struct { + // AvgExecutionPrice The average price at which this order as been executed so far. 0 if the order has not been executed at all. + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + + // ClientOrderId An optional [client-specified order id](/client-order-id#client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // ExecutedAmount The amount of the order that has been filled. + ExecutedAmount *string `json:"executed_amount,omitempty"` + + // IsCancelled `true` if the order has been canceled. Note the spelling, "cancelled" instead of "canceled". This is for compatibility reasons. + IsCancelled *bool `json:"is_cancelled,omitempty"` + + // IsHidden Will always return `false`. + IsHidden *bool `json:"is_hidden,omitempty"` + + // IsLive `true` if the order is active on the book (has remaining quantity and has not been canceled) + IsLive *bool `json:"is_live,omitempty"` + + // Options An array containing at most one supported order execution option. See [Order execution options](/rest/orders#create-new-order) for details. + Options *[]string `json:"options,omitempty"` + + // OrderId The order id + OrderId *string `json:"order_id,omitempty"` + + // OriginalAmount The originally submitted amount of the order. + OriginalAmount *string `json:"original_amount,omitempty"` + + // Price The price the order was issued at + Price *string `json:"price,omitempty"` + + // Reason Populated with the reason your order was canceled, if available. + Reason *string `json:"reason,omitempty"` + + // RemainingAmount The amount of the order that has not been filled. + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *OrderSide `json:"side,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums#symbols-and-minimums) of the order + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Trades Contains an array of JSON objects with trade details. + Trades *[]struct { + // Aggressor If `true`, this order was the taker in the trade + Aggressor *bool `json:"aggressor,omitempty"` + + // Amount The quantity that was executed + Amount *string `json:"amount,omitempty"` + + // Break Will only be present if the trade is broken. See `Break Types` below for more information. + Break *string `json:"break,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The amount charged + FeeAmount *string `json:"fee_amount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"fee_currency,omitempty"` + + // OrderId The order that this trade executed against + OrderId *string `json:"order_id,omitempty"` + + // Price The price that the execution happened at + Price *string `json:"price,omitempty"` + + // Tid Unique identifier for the trade + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type Will be either "Buy" or "Sell", indicating the side of the original order + Type *OrderTradesType `json:"type,omitempty"` + } `json:"trades,omitempty"` + + // Type Description of the order + Type *OrderType `json:"type,omitempty"` + + // WasForced Will always be `false`. + WasForced *bool `json:"was_forced,omitempty"` +} + +// OrderSide defines model for Order.Side. +type OrderSide string + +// OrderTradesType Will be either "Buy" or "Sell", indicating the side of the original order +type OrderTradesType string + +// OrderType Description of the order +type OrderType string + +// OrderBook defines model for OrderBook. +type OrderBook struct { + // Asks The ask price levels currently on the book. These are offers to sell at a given price. + Asks *[]OrderBookEntry `json:"asks,omitempty"` + + // Bids The bid price levels currently on the book. These are offers to buy at a given price. + Bids *[]OrderBookEntry `json:"bids,omitempty"` +} + +// OrderBookEntry defines model for OrderBookEntry. +type OrderBookEntry struct { + // Amount The total quantity remaining at the price + Amount *string `json:"amount,omitempty"` + + // Price The price + Price *string `json:"price,omitempty"` + + // Timestamp **DO NOT USE** - this field is included for compatibility reasons only and is just populated with a dummy value. + Timestamp *string `json:"timestamp,omitempty"` +} + +// OrderStatusRequest defines model for OrderStatusRequest. +type OrderStatusRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // ClientOrderId The `client_order_id` used when placing the order. `client_order_id` cannot be used in combination with `order_id` + ClientOrderId *string `json:"client_order_id,omitempty"` + + // IncludeTrades Either `True` or `False`. If `True` the endpoint will return individual trade details of all fills from the order. + IncludeTrades *bool `json:"include_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order id to get information on. The `order_id` represents a whole number and is transmitted as an unsigned 64-bit integer in JSON format. `order_id` cannot be used in combination with `client_order_id`. + OrderId uint64 `json:"order_id"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// PaymentMethodBalance defines model for PaymentMethodBalance. +type PaymentMethodBalance struct { + // Amount Total account balance for currency. + Amount *string `json:"amount,omitempty"` + + // Available Total amount available for trading + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal Total amount available for withdrawal + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // Currency Symbol for fiat balance. + Currency *string `json:"currency,omitempty"` + + // Type Account type. Will always be `exchange` + Type *string `json:"type,omitempty"` +} + +// PaymentMethodBank defines model for PaymentMethodBank. +type PaymentMethodBank struct { + // Bank Name of bank account + Bank *string `json:"bank,omitempty"` + + // BankId Unique identifier for bank account + BankId *string `json:"bankId,omitempty"` +} + +// PaymentMethodsResponse defines model for PaymentMethodsResponse. +type PaymentMethodsResponse struct { + // Balances Array of JSON objects with available fiat currencies and their balances. + Balances *[]PaymentMethodBalance `json:"balances,omitempty"` + + // Banks Array of JSON objects with banking information + Banks *[]PaymentMethodBank `json:"banks,omitempty"` +} + +// PriceFeedResponse defines model for PriceFeedResponse. +type PriceFeedResponse = []struct { + // Pair Trading pair symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Pair *string `json:"pair,omitempty"` + + // PercentChange24h 24 hour change in price of the pair on the Gemini order book + PercentChange24h *string `json:"percentChange24h,omitempty"` + + // Price Current price of the pair on the Gemini order book + Price *string `json:"price,omitempty"` +} + +// Quantity defines model for Quantity. +type Quantity struct { + // Currency The currency code of the quantity. + Currency string `json:"currency"` + + // Value The value of the quantity. + Value string `json:"value"` +} + +// RevokeOauthTokenResponse defines model for RevokeOauthTokenResponse. +type RevokeOauthTokenResponse struct { + // Message A message that indicates the token has been revoked for the account + Message *string `json:"message,omitempty"` +} + +// RiskStatsResponse defines model for RiskStatsResponse. +type RiskStatsResponse struct { + // IndexPrice Current index price at the time of request + IndexPrice *string `json:"index_price,omitempty"` + + // MarkPrice Current mark price at the time of request + MarkPrice *string `json:"mark_price,omitempty"` + + // OpenInterest string representation of decimal value of open interest + OpenInterest *string `json:"open_interest,omitempty"` + + // OpenInterestNotional string representation of decimal value of open interest notional + OpenInterestNotional *string `json:"open_interest_notional,omitempty"` + + // ProductType Contract type for which the symbol data is fetched + ProductType *RiskStatsResponseProductType `json:"product_type,omitempty"` +} + +// RiskStatsResponseProductType Contract type for which the symbol data is fetched +type RiskStatsResponseProductType string + +// RoleResponse defines model for RoleResponse. +type RoleResponse struct { + // CounterpartyId _Only returned for master-level API keys_. The Gemini clearing counterparty ID associated with the API key making the request. + CounterpartyId *string `json:"counterparty_id,omitempty"` + + // IsAccountAdmin _Only returned for master-level API keys_.`True` if the Administrator role is assigned to the API keys. `False` otherwise. + IsAccountAdmin *bool `json:"isAccountAdmin,omitempty"` + + // IsAuditor `True` if the Auditor role is assigned to the API keys. `False` otherwise. + IsAuditor bool `json:"isAuditor"` + + // IsFundManager `True` if the Fund Manager role is assigned to the API keys. `False` otherwise. + IsFundManager bool `json:"isFundManager"` + + // IsTrader `True` if the Trader role is assigned to the API keys. `False` otherwise. + IsTrader bool `json:"isTrader"` +} + +// StakingBalance defines model for StakingBalance. +type StakingBalance struct { + // Available The amount that is available to trade + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The Staking amount that is available to redeem to exchange account + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Balance The current Staking balance + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + BalanceByProvider *map[string]struct { + // Balance The current Staking balance per providerId + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + } `json:"balanceByProvider,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` + + // Type Will always be "Staking" + Type *string `json:"type,omitempty"` +} + +// StakingDeposit defines model for StakingDeposit. +type StakingDeposit struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rates A JSON object including one or many rates. If more than one rate it would be an array of rates. + Rates *struct { + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *int `json:"rate,omitempty"` + } `json:"rates,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StakingHistory defines model for StakingHistory. +type StakingHistory struct { + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + Transactions *[]StakingTransaction `json:"transactions,omitempty"` +} + +// StakingRate defines model for StakingRate. +type StakingRate struct { + // ApyPct Staking interest APY (Expressed as a percentage derived from the rate and rounded to 1/10th of a percent.) + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // DepositUsdLimit Maximum new amount in USD notional of this crypto that can participate in Gemini Staking per account per month + DepositUsdLimit *int `json:"depositUsdLimit,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *openapi_types.DecimalNumber `json:"rate,omitempty"` + + // RatePct `rate` expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRateProvider Currency Symbol Keys +type StakingRateProvider struct { + CurrencySymbol *StakingRate `json:"currency_symbol,omitempty"` +} + +// StakingRateResponse Provider UUID Keys +type StakingRateResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRateProvider `json:"provider_uuid,omitempty"` +} + +// StakingRewardPeriod defines model for StakingRewardPeriod. +type StakingRewardPeriod struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // ApyPct Staking reward rate expressed as an APY at time of accrual. Interest on Staking balances compounds daily based on the simple rate which is available from `/v1/staking/rates/` + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // FirstAccrualAt Time of first accrual. In iso datetime with timezone format + FirstAccrualAt *string `json:"firstAccrualAt,omitempty"` + + // LastAccrualAt Time of last accrual. In iso datetime with timezone format + LastAccrualAt *string `json:"lastAccrualAt,omitempty"` + + // NumberOfAccruals Number of accruals in the specific aggregate, typically one per day. If the rate is adjusted, new accruals are added. + NumberOfAccruals *int `json:"numberOfAccruals,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePct Rate expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRewards defines model for StakingRewards. +type StakingRewards struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePeriods Array of JSON objects with period accrual information + RatePeriods *[]StakingRewardPeriod `json:"ratePeriods,omitempty"` +} + +// StakingRewardsProvider Currency Symbol Keys +type StakingRewardsProvider struct { + CurrencySymbol *StakingRewards `json:"currency_symbol,omitempty"` +} + +// StakingRewardsResponse Provider UUID Keys +type StakingRewardsResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRewardsProvider `json:"provider_uuid,omitempty"` +} + +// StakingTransaction defines model for StakingTransaction. +type StakingTransaction struct { + // Amount The amount that is defined by the transactionType above + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountCurrency Currency code + AmountCurrency *string `json:"amountCurrency,omitempty"` + + // DateTime timestamp + DateTime *TimestampType `json:"dateTime,omitempty"` + + // PriceAmount Current market price of the underlying token at the time of the reward + PriceAmount *openapi_types.DecimalNumber `json:"priceAmount,omitempty"` + + // PriceCurrency A supported three-letter fiat currency code, e.g. usd + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` + + // TransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment + TransactionType *StakingTransactionTransactionType `json:"transactionType,omitempty"` +} + +// StakingTransactionTransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment +type StakingTransactionTransactionType string + +// StakingWithdrawal defines model for StakingWithdrawal. +type StakingWithdrawal struct { + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountPaidSoFar The amount redeemed successfully + AmountPaidSoFar *openapi_types.DecimalNumber `json:"amountPaidSoFar,omitempty"` + + // AmountRemaining The amount pending to be redeemed + AmountRemaining *openapi_types.DecimalNumber `json:"amountRemaining,omitempty"` + + // Currency Currency code + Currency *string `json:"currency,omitempty"` + + // RequestInitiated In ISO datetime with timezone format + RequestInitiated *string `json:"requestInitiated,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StopLimitOrderResponse defines model for StopLimitOrderResponse. +type StopLimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Side *StopLimitOrderResponseSide `json:"side,omitempty"` + StopPrice *string `json:"stop_price,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *StopLimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// StopLimitOrderResponseSide defines model for StopLimitOrderResponse.Side. +type StopLimitOrderResponseSide string + +// StopLimitOrderResponseType defines model for StopLimitOrderResponse.Type. +type StopLimitOrderResponseType string + +// SymbolDetails defines model for SymbolDetails. +type SymbolDetails struct { + // BaseCurrency CCY1 or the top currency. (i.e `BTC` in `BTCUSD`) + BaseCurrency *string `json:"base_currency,omitempty"` + + // ContractPriceCurrency CCY2 or the quote currency for spot instrument (i.e. `USD` in `BTCUSD`) + // Or collateral currency of the contract in case of perpetual swap instrument. + ContractPriceCurrency *string `json:"contract_price_currency,omitempty"` + + // ContractType `vanilla` / `linear` / `inverse` where `vanilla` is for spot + // while `linear` is for perpetual swap and `inverse` is a special case perpetual swap where the perpetual contract will be settled in base currency. + ContractType *string `json:"contract_type,omitempty"` + + // MinOrderSize The minimum order size in `base_currency` units (i.e `0.00001`) + MinOrderSize *string `json:"min_order_size,omitempty"` + + // ProductType Instrument type `spot` / `swap` -- where `swap` signifies `perpetual swap`. + ProductType *string `json:"product_type,omitempty"` + + // QuoteCurrency CCY2 or the quote currency. (i.e `USD` in `BTCUSD`) + QuoteCurrency *string `json:"quote_currency,omitempty"` + + // QuoteIncrement The number of decimal places in the `quote_currency` (i.e `0.01`) + QuoteIncrement *openapi_types.DecimalNumber `json:"quote_increment,omitempty"` + + // Status Status of the current order book. Can be `open`, `closed`, `cancel_only`, `post_only`, `limit_only`. + Status *string `json:"status,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` + + // TickSize The number of decimal places in the `base_currency`. (i.e `1e-8`) + TickSize *openapi_types.DecimalNumber `json:"tick_size,omitempty"` + + // WrapEnabled When `True`, symbol can be wrapped using this endpoint: + // `POST https://api.gemini.com/v1/wrap/:symbol` + WrapEnabled *bool `json:"wrap_enabled,omitempty"` +} + +// Ticker defines model for Ticker. +type Ticker struct { + // Ask The lowest ask currently available + Ask *string `json:"ask,omitempty"` + + // Bid The highest bid currently available + Bid *string `json:"bid,omitempty"` + + // Last The price of the last executed trade + Last *string `json:"last,omitempty"` + + // Volume Information about the 24 hour volume on the exchange. See properties below + Volume *struct { + // PriceSymbol The volume denominated in the price currency + PriceSymbol *string `json:"price_symbol,omitempty"` + + // QuantitySymbol The volume denominated in the quantity currency + QuantitySymbol *string `json:"quantity_symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + } `json:"volume,omitempty"` +} + +// TickerInfo defines model for TickerInfo. +type TickerInfo struct { + // Ask Current best offer + Ask *string `json:"ask,omitempty"` + + // Bid Current best bid + Bid *string `json:"bid,omitempty"` + + // Changes Hourly prices descending for past 24 hours + Changes *[]string `json:"changes,omitempty"` + + // Close Close price (most recent trade) + Close *string `json:"close,omitempty"` + + // High High price from 24 hours ago + High *string `json:"high,omitempty"` + + // Low Low price from 24 hours ago + Low *string `json:"low,omitempty"` + + // Open Open price from 24 hours ago + Open *string `json:"open,omitempty"` + + // Symbol The trading pair symbol + Symbol *string `json:"symbol,omitempty"` +} + +// TimestampType timestamp +type TimestampType struct { + union json.RawMessage +} + +// TimestampType0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `1495127793` | `POST` only | +// | string (milliseconds) | `1495127793000` | `POST` only | +type TimestampType0 = string + +// TimestampType1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type TimestampType1 = int64 + +// Trade defines model for Trade. +type Trade struct { + // Amount The amount that was traded + Amount *string `json:"amount,omitempty"` + + // Broken Whether the trade was broken or not. Broken trades will not be displayed by default; use the `include_breaks` to display them. + Broken *bool `json:"broken,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // Price The price the trade was executed at + Price *string `json:"price,omitempty"` + + // Tid The trade ID number + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type - `buy` means that an ask was removed from the book by an incoming buy order. + // - `sell` means that a bid was removed from the book by an incoming sell order. + Type *TradeType `json:"type,omitempty"` +} + +// TradeType - `buy` means that an ask was removed from the book by an incoming buy order. +// - `sell` means that a bid was removed from the book by an incoming sell order. +type TradeType string + +// TradeVolume defines model for TradeVolume. +type TradeVolume struct { + BaseCurrency *string `json:"base_currency,omitempty"` + BuyMakerBase *string `json:"buy_maker_base,omitempty"` + BuyMakerCount *int `json:"buy_maker_count,omitempty"` + BuyMakerNotional *string `json:"buy_maker_notional,omitempty"` + BuyTakerBase *string `json:"buy_taker_base,omitempty"` + BuyTakerCount *int `json:"buy_taker_count,omitempty"` + BuyTakerNotional *string `json:"buy_taker_notional,omitempty"` + DataDate *string `json:"data_date,omitempty"` + MakerBuySellRatio *string `json:"maker_buy_sell_ratio,omitempty"` + NotionalCurrency *string `json:"notional_currency,omitempty"` + QuoteCurrency *string `json:"quote_currency,omitempty"` + SellMakerBase *string `json:"sell_maker_base,omitempty"` + SellMakerCount *int `json:"sell_maker_count,omitempty"` + SellMakerNotional *string `json:"sell_maker_notional,omitempty"` + SellTakerBase *string `json:"sell_taker_base,omitempty"` + SellTakerCount *int `json:"sell_taker_count,omitempty"` + SellTakerNotional *string `json:"sell_taker_notional,omitempty"` + Symbol *string `json:"symbol,omitempty"` + TotalVolumeBase *string `json:"total_volume_base,omitempty"` +} + +// Transaction defines model for Transaction. +type Transaction struct { + union json.RawMessage +} + +// Transaction0 Trade Reponse +type Transaction0 struct { + // Account The account. + Account *string `json:"account,omitempty"` + + // Amount The quantity that was executed. + Amount *string `json:"amount,omitempty"` + + // ClientOrderId The client order ID, if defined. Otherwise an empty string. + ClientOrderId *string `json:"clientOrderId,omitempty"` + + // Exchange Will always be "gemini". + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeAssetCode The symbol that the trade was for + FeeAssetCode *string `json:"feeAssetCode,omitempty"` + + // IsAggressor If true, this order was the taker in the trade. + IsAggressor *bool `json:"isAggressor,omitempty"` + + // IsAuctionFill True if the trade was a auction trade and not an on-exchange trade. + IsAuctionFill *bool `json:"isAuctionFill,omitempty"` + + // IsClearingFill True if the trade was a clearing trade and not an on-exchange trade. + IsClearingFill *bool `json:"isClearingFill,omitempty"` + + // OrderId The order that this trade executed against. + OrderId *int64 `json:"orderId,omitempty"` + + // Price The price that the execution happened at. + Price *string `json:"price,omitempty"` + + // Side Indicating the side of the original order. + Side *string `json:"side,omitempty"` + + // Symbol The symbol that the trade was for. + Symbol *string `json:"symbol,omitempty"` + + // Tid The trade ID. + Tid *int64 `json:"tid,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` +} + +// Transaction1 Transfer Reponse +type Transaction1 struct { + // AdvanceEid Deposit advance event ID. + AdvanceEid *int64 `json:"advanceEid,omitempty"` + + // Amount The quantity that was transferred. + Amount *string `json:"amount,omitempty"` + + // BankId Bank ID. + BankId *string `json:"bankId,omitempty"` + + // ClientTransferId Client Transfer ID. Client transfer ID is an optional client-supplied unique identifier for each withdrawal or internal transfer. + ClientTransferId *string `json:"clientTransferId,omitempty"` + + // CorrelationId Correlation ID. + CorrelationId *int64 `json:"correlationId,omitempty"` + + // Currency Currency code, see symbols + Currency *string `json:"currency,omitempty"` + + // Destination The account you are transferring to. + Destination *string `json:"destination,omitempty"` + + // Eid Transfer event id. + Eid *int64 `json:"eid,omitempty"` + + // FeeId Fee ID. + FeeId *string `json:"feeId,omitempty"` + + // Method Type of transfer method. + Method *string `json:"method,omitempty"` + + // OperationReason The operation reason. + OperationReason *string `json:"operationReason,omitempty"` + + // PendingEid Pending event ID. + PendingEid *int64 `json:"pendingEid,omitempty"` + + // Purpose Purpose. + Purpose *string `json:"purpose,omitempty"` + + // Source The account you are transferring from. + Source *string `json:"source,omitempty"` + + // Status The status of the transfer. + Status *string `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TransactionHash Supplies the transaction hash when available. + TransactionHash *string `json:"transactionHash,omitempty"` + + // TransferId Transfer ID. + TransferId *string `json:"transferId,omitempty"` + + // TransferType Transfer type. + TransferType *string `json:"transferType,omitempty"` + + // WithdrawalEid Withdrawal event ID. + WithdrawalEid *int64 `json:"withdrawalEid,omitempty"` + + // WithdrawalId Withdrawal ID. + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// Transfer defines model for Transfer. +type Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Eid The transfer ID + Eid *int64 `json:"eid,omitempty"` + Status *TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The transaction hash if applicable + TxHash *string `json:"txHash,omitempty"` + Type *TransferType `json:"type,omitempty"` +} + +// TransferStatus defines model for Transfer.Status. +type TransferStatus string + +// TransferType defines model for Transfer.Type. +type TransferType string + +// V2Transfer defines model for V2Transfer. +type V2Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Destination The destination address for withdrawals + Destination *string `json:"destination,omitempty"` + + // Eid The transfer event ID + Eid *int64 `json:"eid,omitempty"` + + // FeeAmount The fee charged for the transfer + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency The currency in which the fee was charged + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // Method The transfer method (e.g., `ACH`, `CreditCard`) + Method *string `json:"method,omitempty"` + + // Network The blockchain network the transfer was executed on (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`). Not present for fiat or administrative transfers. + Network *string `json:"network,omitempty"` + + // OutputIdx The output index for withdrawals + OutputIdx *int `json:"outputIdx,omitempty"` + + // Purpose The purpose or reason for administrative transfers + Purpose *string `json:"purpose,omitempty"` + + // Status The status of the transfer + Status *V2TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The on-chain transaction hash, if applicable + TxHash *string `json:"txHash,omitempty"` + + // Type The type of the transfer + Type *V2TransferType `json:"type,omitempty"` + + // WithdrawalId The unique withdrawal identifier + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// V2TransferStatus The status of the transfer +type V2TransferStatus string + +// V2TransferType The type of the transfer +type V2TransferType string + +// WithdrawCryptoFundsResponse Response returned after submitting a v2 cryptocurrency withdrawal. +type WithdrawCryptoFundsResponse struct { + // Address Standard string format of the withdrawal destination address + Address *string `json:"address,omitempty"` + + // Amount The withdrawal amount + Amount *string `json:"amount,omitempty"` + + // Currency The currency code of the withdrawn asset + Currency *string `json:"currency,omitempty"` + + // Fee The fee charged for the withdrawal + Fee *string `json:"fee,omitempty"` + + // WithdrawalId A unique ID for the withdrawal + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// ApiKeyAuth defines model for apiKeyAuth. +type ApiKeyAuth = string + +// CacheControl defines model for cacheControl. +type CacheControl = string + +// ContentLength defines model for contentLength. +type ContentLength = string + +// ContentType defines model for contentType. +type ContentType = string + +// CurrencyParam defines model for currencyParam. +type CurrencyParam = string + +// NetworkParam defines model for networkParam. +type NetworkParam = string + +// PayloadAuth defines model for payloadAuth. +type PayloadAuth = string + +// SignatureAuth defines model for signatureAuth. +type SignatureAuth = string + +// SymbolParam defines model for symbolParam. +type SymbolParam = string + +// TimestampParam timestamp +type TimestampParam = TimestampType + +// ApiKeyIpFilteringFailure defines model for ApiKeyIpFilteringFailure. +type ApiKeyIpFilteringFailure = ErrorResponse + +// BadRequest defines model for BadRequest. +type BadRequest = ErrorResponse + +// InternalError defines model for InternalError. +type InternalError = ErrorResponse + +// NotFound defines model for NotFound. +type NotFound = ErrorResponse + +// TooManyRequests defines model for TooManyRequests. +type TooManyRequests = ErrorResponse + +// Unauthorized defines model for Unauthorized. +type Unauthorized = ErrorResponse + +// apiKeyAuthContextKey is the context key for apiKeyAuth security scheme +type apiKeyAuthContextKey string + +// payloadAuthContextKey is the context key for payloadAuth security scheme +type payloadAuthContextKey string + +// signatureAuthContextKey is the context key for signatureAuth security scheme +type signatureAuthContextKey string + +// GetAccountMarginJSONBody defines parameters for GetAccountMargin. +type GetAccountMarginJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // Symbol Trading pair symbol. See [symbols and minimums](/market-data/symbols-and-minimums) + Symbol string `json:"symbol"` +} + +// GetAccountMarginParams defines parameters for GetAccountMargin. +type GetAccountMarginParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListFundingPaymentsJSONBody defines parameters for ListFundingPayments. +type ListFundingPaymentsJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// ListFundingPaymentsParams defines parameters for ListFundingPayments. +type ListFundingPaymentsParams struct { + // Since If specified, only return funding payments after this point. Default value is 24h in past. See [**Timestamps**](/rest/~schemas#timestamp-type) for more information + Since *TimestampType `form:"since,omitempty" json:"since,omitempty"` + + // To If specified, only returns funding payment until this point. Default value is now. See [**Timestamps**](/rest/~schemas#timestamp-type) for more information + To *TimestampType `form:"to,omitempty" json:"to,omitempty"` + + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetFundingPaymentReportJsonJSONBody defines parameters for GetFundingPaymentReportJson. +type GetFundingPaymentReportJsonJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// GetFundingPaymentReportJsonParams defines parameters for GetFundingPaymentReportJson. +type GetFundingPaymentReportJsonParams struct { + // FromDate If empty, will only fetch records by numRows value. + FromDate *openapi_types.Date `form:"fromDate,omitempty" json:"fromDate,omitempty"` + + // ToDate If empty, will only fetch records by numRows value. + ToDate *openapi_types.Date `form:"toDate,omitempty" json:"toDate,omitempty"` + + // NumRows If empty, default value '8760' + NumRows *int `form:"numRows,omitempty" json:"numRows,omitempty"` + + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetFundingPaymentReportFileJSONBody defines parameters for GetFundingPaymentReportFile. +type GetFundingPaymentReportFileJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// GetFundingPaymentReportFileParams defines parameters for GetFundingPaymentReportFile. +type GetFundingPaymentReportFileParams struct { + // FromDate If empty, will only fetch records by numRows value. + FromDate *openapi_types.Date `form:"fromDate,omitempty" json:"fromDate,omitempty"` + + // ToDate If empty, will only fetch records by numRows value. + ToDate *openapi_types.Date `form:"toDate,omitempty" json:"toDate,omitempty"` + + // NumRows If empty, default value '8760' + NumRows *int `form:"numRows,omitempty" json:"numRows,omitempty"` + + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetOpenPositionsJSONBody defines parameters for GetOpenPositions. +type GetOpenPositionsJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which the orders were placed. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/positions" + Request string `json:"request"` +} + +// GetOpenPositionsParams defines parameters for GetOpenPositions. +type GetOpenPositionsParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetAccountMarginJSONRequestBody defines body for GetAccountMargin for application/json ContentType. +type GetAccountMarginJSONRequestBody GetAccountMarginJSONBody + +// ListFundingPaymentsJSONRequestBody defines body for ListFundingPayments for application/json ContentType. +type ListFundingPaymentsJSONRequestBody ListFundingPaymentsJSONBody + +// GetFundingPaymentReportJsonJSONRequestBody defines body for GetFundingPaymentReportJson for application/json ContentType. +type GetFundingPaymentReportJsonJSONRequestBody GetFundingPaymentReportJsonJSONBody + +// GetFundingPaymentReportFileJSONRequestBody defines body for GetFundingPaymentReportFile for application/json ContentType. +type GetFundingPaymentReportFileJSONRequestBody GetFundingPaymentReportFileJSONBody + +// GetOpenPositionsJSONRequestBody defines body for GetOpenPositions for application/json ContentType. +type GetOpenPositionsJSONRequestBody GetOpenPositionsJSONBody + +// AsHeartbeatNonce0 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce0 +func (t Heartbeat_Nonce) AsHeartbeatNonce0() (HeartbeatNonce0, error) { + var body HeartbeatNonce0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce0 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) FromHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce0 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsHeartbeatNonce1 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce1 +func (t Heartbeat_Nonce) AsHeartbeatNonce1() (HeartbeatNonce1, error) { + var body HeartbeatNonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce1 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) FromHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce1 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Heartbeat_Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Heartbeat_Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType returns the union data inside the Nonce as a TimestampType +func (t Nonce) AsTimestampType() (TimestampType, error) { + var body TimestampType + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType overwrites any union data inside the Nonce as the provided TimestampType +func (t *Nonce) FromTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType performs a merge with any union data inside the Nonce, using the provided TimestampType +func (t *Nonce) MergeTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNonce1 returns the union data inside the Nonce as a Nonce1 +func (t Nonce) AsNonce1() (Nonce1, error) { + var body Nonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNonce1 overwrites any union data inside the Nonce as the provided Nonce1 +func (t *Nonce) FromNonce1(v Nonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNonce1 performs a merge with any union data inside the Nonce, using the provided Nonce1 +func (t *Nonce) MergeNonce1(v Nonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType0 returns the union data inside the TimestampType as a TimestampType0 +func (t TimestampType) AsTimestampType0() (TimestampType0, error) { + var body TimestampType0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType0 overwrites any union data inside the TimestampType as the provided TimestampType0 +func (t *TimestampType) FromTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType0 performs a merge with any union data inside the TimestampType, using the provided TimestampType0 +func (t *TimestampType) MergeTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTimestampType1 returns the union data inside the TimestampType as a TimestampType1 +func (t TimestampType) AsTimestampType1() (TimestampType1, error) { + var body TimestampType1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType1 overwrites any union data inside the TimestampType as the provided TimestampType1 +func (t *TimestampType) FromTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType1 performs a merge with any union data inside the TimestampType, using the provided TimestampType1 +func (t *TimestampType) MergeTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t TimestampType) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *TimestampType) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTransaction0 returns the union data inside the Transaction as a Transaction0 +func (t Transaction) AsTransaction0() (Transaction0, error) { + var body Transaction0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction0 overwrites any union data inside the Transaction as the provided Transaction0 +func (t *Transaction) FromTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction0 performs a merge with any union data inside the Transaction, using the provided Transaction0 +func (t *Transaction) MergeTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTransaction1 returns the union data inside the Transaction as a Transaction1 +func (t Transaction) AsTransaction1() (Transaction1, error) { + var body Transaction1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction1 overwrites any union data inside the Transaction as the provided Transaction1 +func (t *Transaction) FromTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction1 performs a merge with any union data inside the Transaction, using the provided Transaction1 +func (t *Transaction) MergeTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Transaction) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Transaction) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/packages/sdk-go/generated/predictions/types.gen.go b/packages/sdk-go/generated/predictions/types.gen.go new file mode 100644 index 0000000..689cb65 --- /dev/null +++ b/packages/sdk-go/generated/predictions/types.gen.go @@ -0,0 +1,3251 @@ +// Code generated from prediction-markets.yaml (Combos, Markets, Positions, Rewards, Terms, Trading, Volume). DO NOT EDIT. + +// Package predictions provides primitives to interact with the openapi HTTP API. +// +// Code generated by oapi-codegen. DO NOT EDIT. +package predictions + +import ( + "encoding/json" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/internal/runtime" + openapi_types "github.com/gemini/developer-platform/packages/sdk-go/types" +) + +const ( + ApiKeyScopes apiKeyContextKey = "apiKey.Scopes" + PayloadAuthScopes payloadAuthContextKey = "payloadAuth.Scopes" + SignatureAuthScopes signatureAuthContextKey = "signatureAuth.Scopes" +) + +// Defines values for AccountGroupBlockedErrorCode. +const ( + ACCOUNTGROUPBLOCKED AccountGroupBlockedErrorCode = "ACCOUNT_GROUP_BLOCKED" +) + +// Valid indicates whether the value is a known member of the AccountGroupBlockedErrorCode enum. +func (e AccountGroupBlockedErrorCode) Valid() bool { + switch e { + case ACCOUNTGROUPBLOCKED: + return true + default: + return false + } +} + +// Defines values for AccountGroupBlockedErrorError. +const ( + ThisAccountIsNotPermittedToTradePredictionMarkets AccountGroupBlockedErrorError = "This account is not permitted to trade prediction markets" +) + +// Valid indicates whether the value is a known member of the AccountGroupBlockedErrorError enum. +func (e AccountGroupBlockedErrorError) Valid() bool { + switch e { + case ThisAccountIsNotPermittedToTradePredictionMarkets: + return true + default: + return false + } +} + +// Defines values for AuthErrorResponseResult. +const ( + AuthErrorResponseResultError AuthErrorResponseResult = "error" +) + +// Valid indicates whether the value is a known member of the AuthErrorResponseResult enum. +func (e AuthErrorResponseResult) Valid() bool { + switch e { + case AuthErrorResponseResultError: + return true + default: + return false + } +} + +// Defines values for BatchOrderResponseStatus. +const ( + BatchOrderResponseStatusCancelled BatchOrderResponseStatus = "cancelled" + BatchOrderResponseStatusClosed BatchOrderResponseStatus = "closed" + BatchOrderResponseStatusFilled BatchOrderResponseStatus = "filled" + BatchOrderResponseStatusOpen BatchOrderResponseStatus = "open" +) + +// Valid indicates whether the value is a known member of the BatchOrderResponseStatus enum. +func (e BatchOrderResponseStatus) Valid() bool { + switch e { + case BatchOrderResponseStatusCancelled: + return true + case BatchOrderResponseStatusClosed: + return true + case BatchOrderResponseStatusFilled: + return true + case BatchOrderResponseStatusOpen: + return true + default: + return false + } +} + +// Defines values for BatchOrderResponseTimeInForce. +const ( + BatchOrderResponseTimeInForceFillOrKill BatchOrderResponseTimeInForce = "fill-or-kill" + BatchOrderResponseTimeInForceGoodTilCancel BatchOrderResponseTimeInForce = "good-til-cancel" + BatchOrderResponseTimeInForceImmediateOrCancel BatchOrderResponseTimeInForce = "immediate-or-cancel" + BatchOrderResponseTimeInForceMakerOrCancel BatchOrderResponseTimeInForce = "maker-or-cancel" +) + +// Valid indicates whether the value is a known member of the BatchOrderResponseTimeInForce enum. +func (e BatchOrderResponseTimeInForce) Valid() bool { + switch e { + case BatchOrderResponseTimeInForceFillOrKill: + return true + case BatchOrderResponseTimeInForceGoodTilCancel: + return true + case BatchOrderResponseTimeInForceImmediateOrCancel: + return true + case BatchOrderResponseTimeInForceMakerOrCancel: + return true + default: + return false + } +} + +// Defines values for CancelOrderBatchSuccessResultResult. +const ( + Ok CancelOrderBatchSuccessResultResult = "ok" +) + +// Valid indicates whether the value is a known member of the CancelOrderBatchSuccessResultResult enum. +func (e CancelOrderBatchSuccessResultResult) Valid() bool { + switch e { + case Ok: + return true + default: + return false + } +} + +// Defines values for CashedOutPositionSide. +const ( + CashedOutPositionSideSell CashedOutPositionSide = "sell" +) + +// Valid indicates whether the value is a known member of the CashedOutPositionSide enum. +func (e CashedOutPositionSide) Valid() bool { + switch e { + case CashedOutPositionSideSell: + return true + default: + return false + } +} + +// Defines values for ComboLegRequiredOutcome. +const ( + ComboLegRequiredOutcomeNo ComboLegRequiredOutcome = "No" + ComboLegRequiredOutcomeYes ComboLegRequiredOutcome = "Yes" +) + +// Valid indicates whether the value is a known member of the ComboLegRequiredOutcome enum. +func (e ComboLegRequiredOutcome) Valid() bool { + switch e { + case ComboLegRequiredOutcomeNo: + return true + case ComboLegRequiredOutcomeYes: + return true + default: + return false + } +} + +// Defines values for ComboSummaryLegLegOutcome. +const ( + ComboSummaryLegLegOutcomeNo ComboSummaryLegLegOutcome = "No" + ComboSummaryLegLegOutcomeYes ComboSummaryLegLegOutcome = "Yes" +) + +// Valid indicates whether the value is a known member of the ComboSummaryLegLegOutcome enum. +func (e ComboSummaryLegLegOutcome) Valid() bool { + switch e { + case ComboSummaryLegLegOutcomeNo: + return true + case ComboSummaryLegLegOutcomeYes: + return true + default: + return false + } +} + +// Defines values for ComboSummaryLegRequiredOutcome. +const ( + ComboSummaryLegRequiredOutcomeNo ComboSummaryLegRequiredOutcome = "No" + ComboSummaryLegRequiredOutcomeYes ComboSummaryLegRequiredOutcome = "Yes" +) + +// Valid indicates whether the value is a known member of the ComboSummaryLegRequiredOutcome enum. +func (e ComboSummaryLegRequiredOutcome) Valid() bool { + switch e { + case ComboSummaryLegRequiredOutcomeNo: + return true + case ComboSummaryLegRequiredOutcomeYes: + return true + default: + return false + } +} + +// Defines values for ContractMarketState. +const ( + ContractMarketStateClosed ContractMarketState = "closed" + ContractMarketStateOpen ContractMarketState = "open" +) + +// Valid indicates whether the value is a known member of the ContractMarketState enum. +func (e ContractMarketState) Valid() bool { + switch e { + case ContractMarketStateClosed: + return true + case ContractMarketStateOpen: + return true + default: + return false + } +} + +// Defines values for CreateComboLegRequiredOutcome. +const ( + CreateComboLegRequiredOutcomeNo CreateComboLegRequiredOutcome = "No" + CreateComboLegRequiredOutcomeYes CreateComboLegRequiredOutcome = "Yes" +) + +// Valid indicates whether the value is a known member of the CreateComboLegRequiredOutcome enum. +func (e CreateComboLegRequiredOutcome) Valid() bool { + switch e { + case CreateComboLegRequiredOutcomeNo: + return true + case CreateComboLegRequiredOutcomeYes: + return true + default: + return false + } +} + +// Defines values for LiquidityRewardEventPoolSource. +const ( + CategoryDefault LiquidityRewardEventPoolSource = "category_default" + EventOverride LiquidityRewardEventPoolSource = "event_override" + Unspecified LiquidityRewardEventPoolSource = "unspecified" +) + +// Valid indicates whether the value is a known member of the LiquidityRewardEventPoolSource enum. +func (e LiquidityRewardEventPoolSource) Valid() bool { + switch e { + case CategoryDefault: + return true + case EventOverride: + return true + case Unspecified: + return true + default: + return false + } +} + +// Defines values for MarketStatus. +const ( + MarketStatusActive MarketStatus = "active" + MarketStatusApproved MarketStatus = "approved" + MarketStatusClosed MarketStatus = "closed" + MarketStatusInvalid MarketStatus = "invalid" + MarketStatusSettled MarketStatus = "settled" + MarketStatusUnderReview MarketStatus = "under_review" +) + +// Valid indicates whether the value is a known member of the MarketStatus enum. +func (e MarketStatus) Valid() bool { + switch e { + case MarketStatusActive: + return true + case MarketStatusApproved: + return true + case MarketStatusClosed: + return true + case MarketStatusInvalid: + return true + case MarketStatusSettled: + return true + case MarketStatusUnderReview: + return true + default: + return false + } +} + +// Defines values for MarketType. +const ( + Binary MarketType = "binary" + Categorical MarketType = "categorical" +) + +// Valid indicates whether the value is a known member of the MarketType enum. +func (e MarketType) Valid() bool { + switch e { + case Binary: + return true + case Categorical: + return true + default: + return false + } +} + +// Defines values for OrderSide. +const ( + OrderSideBuy OrderSide = "buy" + OrderSideSell OrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the OrderSide enum. +func (e OrderSide) Valid() bool { + switch e { + case OrderSideBuy: + return true + case OrderSideSell: + return true + default: + return false + } +} + +// Defines values for OrderStatus. +const ( + OrderStatusCancelled OrderStatus = "cancelled" + OrderStatusFilled OrderStatus = "filled" + OrderStatusOpen OrderStatus = "open" +) + +// Valid indicates whether the value is a known member of the OrderStatus enum. +func (e OrderStatus) Valid() bool { + switch e { + case OrderStatusCancelled: + return true + case OrderStatusFilled: + return true + case OrderStatusOpen: + return true + default: + return false + } +} + +// Defines values for OrderType. +const ( + OrderTypeLimit OrderType = "limit" + OrderTypeStopLimit OrderType = "stop-limit" +) + +// Valid indicates whether the value is a known member of the OrderType enum. +func (e OrderType) Valid() bool { + switch e { + case OrderTypeLimit: + return true + case OrderTypeStopLimit: + return true + default: + return false + } +} + +// Defines values for Outcome. +const ( + No Outcome = "no" + Yes Outcome = "yes" +) + +// Valid indicates whether the value is a known member of the Outcome enum. +func (e Outcome) Valid() bool { + switch e { + case No: + return true + case Yes: + return true + default: + return false + } +} + +// Defines values for PositionStatus. +const ( + PositionStatusActive PositionStatus = "active" + PositionStatusCancelled PositionStatus = "cancelled" + PositionStatusResolved PositionStatus = "resolved" +) + +// Valid indicates whether the value is a known member of the PositionStatus enum. +func (e PositionStatus) Valid() bool { + switch e { + case PositionStatusActive: + return true + case PositionStatusCancelled: + return true + case PositionStatusResolved: + return true + default: + return false + } +} + +// Defines values for RestrictedSellOnlyErrorError. +const ( + ACCOUNTRESTRICTEDSELLONLY RestrictedSellOnlyErrorError = "ACCOUNT_RESTRICTED_SELL_ONLY" +) + +// Valid indicates whether the value is a known member of the RestrictedSellOnlyErrorError enum. +func (e RestrictedSellOnlyErrorError) Valid() bool { + switch e { + case ACCOUNTRESTRICTEDSELLONLY: + return true + default: + return false + } +} + +// Defines values for RestrictedSellOnlyErrorMessage. +const ( + YourAccountIsRestrictedToSellingExistingPositionsBuyingIsNotPermitted RestrictedSellOnlyErrorMessage = "Your account is restricted to selling existing positions; buying is not permitted." +) + +// Valid indicates whether the value is a known member of the RestrictedSellOnlyErrorMessage enum. +func (e RestrictedSellOnlyErrorMessage) Valid() bool { + switch e { + case YourAccountIsRestrictedToSellingExistingPositionsBuyingIsNotPermitted: + return true + default: + return false + } +} + +// Defines values for SportsMarketMetric. +const ( + SportsMarketMetricAces SportsMarketMetric = "aces" + SportsMarketMetricAssists SportsMarketMetric = "assists" + SportsMarketMetricBallsFaced SportsMarketMetric = "balls_faced" + SportsMarketMetricBirdies SportsMarketMetric = "birdies" + SportsMarketMetricBlockedShots SportsMarketMetric = "blocked_shots" + SportsMarketMetricBlocks SportsMarketMetric = "blocks" + SportsMarketMetricBogeys SportsMarketMetric = "bogeys" + SportsMarketMetricBoundaries SportsMarketMetric = "boundaries" + SportsMarketMetricBreakPointsWon SportsMarketMetric = "break_points_won" + SportsMarketMetricCards SportsMarketMetric = "cards" + SportsMarketMetricCatches SportsMarketMetric = "catches" + SportsMarketMetricCleanSheets SportsMarketMetric = "clean_sheets" + SportsMarketMetricCompletedPasses SportsMarketMetric = "completed_passes" + SportsMarketMetricControlTime SportsMarketMetric = "control_time" + SportsMarketMetricCorners SportsMarketMetric = "corners" + SportsMarketMetricDefensiveRebounds SportsMarketMetric = "defensive_rebounds" + SportsMarketMetricDoubleDouble SportsMarketMetric = "double_double" + SportsMarketMetricDoubleFaults SportsMarketMetric = "double_faults" + SportsMarketMetricDoubles SportsMarketMetric = "doubles" + SportsMarketMetricEagles SportsMarketMetric = "eagles" + SportsMarketMetricEarnedRuns SportsMarketMetric = "earned_runs" + SportsMarketMetricErrors SportsMarketMetric = "errors" + SportsMarketMetricFaceoffWins SportsMarketMetric = "faceoff_wins" + SportsMarketMetricFairwaysHit SportsMarketMetric = "fairways_hit" + SportsMarketMetricFantasyPoints SportsMarketMetric = "fantasy_points" + SportsMarketMetricFastestLap SportsMarketMetric = "fastest_lap" + SportsMarketMetricFieldGoalsMade SportsMarketMetric = "field_goals_made" + SportsMarketMetricFinishingPosition SportsMarketMetric = "finishing_position" + SportsMarketMetricFouls SportsMarketMetric = "fouls" + SportsMarketMetricFours SportsMarketMetric = "fours" + SportsMarketMetricFreeThrowsMade SportsMarketMetric = "free_throws_made" + SportsMarketMetricFumbles SportsMarketMetric = "fumbles" + SportsMarketMetricGames SportsMarketMetric = "games" + SportsMarketMetricGoals SportsMarketMetric = "goals" + SportsMarketMetricGoalsAllowed SportsMarketMetric = "goals_allowed" + SportsMarketMetricGreensInRegulation SportsMarketMetric = "greens_in_regulation" + SportsMarketMetricGridPosition SportsMarketMetric = "grid_position" + SportsMarketMetricHits SportsMarketMetric = "hits" + SportsMarketMetricHitsAllowed SportsMarketMetric = "hits_allowed" + SportsMarketMetricHitsRunsRbis SportsMarketMetric = "hits_runs_rbis" + SportsMarketMetricHolesInOne SportsMarketMetric = "holes_in_one" + SportsMarketMetricHomeRuns SportsMarketMetric = "home_runs" + SportsMarketMetricInningsPitched SportsMarketMetric = "innings_pitched" + SportsMarketMetricInterceptionsThrown SportsMarketMetric = "interceptions_thrown" + SportsMarketMetricKickingPoints SportsMarketMetric = "kicking_points" + SportsMarketMetricKnockdowns SportsMarketMetric = "knockdowns" + SportsMarketMetricLapTime SportsMarketMetric = "lap_time" + SportsMarketMetricLapsCompleted SportsMarketMetric = "laps_completed" + SportsMarketMetricLapsLed SportsMarketMetric = "laps_led" + SportsMarketMetricLongestPassCompletion SportsMarketMetric = "longest_pass_completion" + SportsMarketMetricLongestReception SportsMarketMetric = "longest_reception" + SportsMarketMetricLongestRush SportsMarketMetric = "longest_rush" + SportsMarketMetricMaidenOvers SportsMarketMetric = "maiden_overs" + SportsMarketMetricOffensiveRebounds SportsMarketMetric = "offensive_rebounds" + SportsMarketMetricOffsides SportsMarketMetric = "offsides" + SportsMarketMetricOther SportsMarketMetric = "other" + SportsMarketMetricPars SportsMarketMetric = "pars" + SportsMarketMetricPassAttempts SportsMarketMetric = "pass_attempts" + SportsMarketMetricPassCompletions SportsMarketMetric = "pass_completions" + SportsMarketMetricPasses SportsMarketMetric = "passes" + SportsMarketMetricPassingTouchdowns SportsMarketMetric = "passing_touchdowns" + SportsMarketMetricPassingYards SportsMarketMetric = "passing_yards" + SportsMarketMetricPenaltyMinutes SportsMarketMetric = "penalty_minutes" + SportsMarketMetricPitStops SportsMarketMetric = "pit_stops" + SportsMarketMetricPitchingOutsRecorded SportsMarketMetric = "pitching_outs_recorded" + SportsMarketMetricPoints SportsMarketMetric = "points" + SportsMarketMetricPointsAssists SportsMarketMetric = "points_assists" + SportsMarketMetricPointsRebounds SportsMarketMetric = "points_rebounds" + SportsMarketMetricPointsReboundsAssists SportsMarketMetric = "points_rebounds_assists" + SportsMarketMetricPositionsGained SportsMarketMetric = "positions_gained" + SportsMarketMetricPowerPlayPoints SportsMarketMetric = "power_play_points" + SportsMarketMetricPutts SportsMarketMetric = "putts" + SportsMarketMetricQualifyingPosition SportsMarketMetric = "qualifying_position" + SportsMarketMetricRebounds SportsMarketMetric = "rebounds" + SportsMarketMetricReboundsAssists SportsMarketMetric = "rebounds_assists" + SportsMarketMetricReceivingTouchdowns SportsMarketMetric = "receiving_touchdowns" + SportsMarketMetricReceivingYards SportsMarketMetric = "receiving_yards" + SportsMarketMetricReceptions SportsMarketMetric = "receptions" + SportsMarketMetricRedCards SportsMarketMetric = "red_cards" + SportsMarketMetricRetirements SportsMarketMetric = "retirements" + SportsMarketMetricRounds SportsMarketMetric = "rounds" + SportsMarketMetricRuns SportsMarketMetric = "runs" + SportsMarketMetricRunsBattedIn SportsMarketMetric = "runs_batted_in" + SportsMarketMetricRunsConceded SportsMarketMetric = "runs_conceded" + SportsMarketMetricRushAttempts SportsMarketMetric = "rush_attempts" + SportsMarketMetricRushingTouchdowns SportsMarketMetric = "rushing_touchdowns" + SportsMarketMetricRushingYards SportsMarketMetric = "rushing_yards" + SportsMarketMetricSacks SportsMarketMetric = "sacks" + SportsMarketMetricSafetyCars SportsMarketMetric = "safety_cars" + SportsMarketMetricSaves SportsMarketMetric = "saves" + SportsMarketMetricSets SportsMarketMetric = "sets" + SportsMarketMetricShots SportsMarketMetric = "shots" + SportsMarketMetricShotsOnGoal SportsMarketMetric = "shots_on_goal" + SportsMarketMetricShotsOnTarget SportsMarketMetric = "shots_on_target" + SportsMarketMetricShutouts SportsMarketMetric = "shutouts" + SportsMarketMetricSignificantStrikes SportsMarketMetric = "significant_strikes" + SportsMarketMetricSingles SportsMarketMetric = "singles" + SportsMarketMetricSixes SportsMarketMetric = "sixes" + SportsMarketMetricSteals SportsMarketMetric = "steals" + SportsMarketMetricStolenBases SportsMarketMetric = "stolen_bases" + SportsMarketMetricStrikeouts SportsMarketMetric = "strikeouts" + SportsMarketMetricStrokes SportsMarketMetric = "strokes" + SportsMarketMetricSubmissionAttempts SportsMarketMetric = "submission_attempts" + SportsMarketMetricTackles SportsMarketMetric = "tackles" + SportsMarketMetricTakedowns SportsMarketMetric = "takedowns" + SportsMarketMetricThreePointersMade SportsMarketMetric = "three_pointers_made" + SportsMarketMetricTiebreaksWon SportsMarketMetric = "tiebreaks_won" + SportsMarketMetricTotalBases SportsMarketMetric = "total_bases" + SportsMarketMetricTotalPointsWon SportsMarketMetric = "total_points_won" + SportsMarketMetricTotalStrikes SportsMarketMetric = "total_strikes" + SportsMarketMetricTouchdowns SportsMarketMetric = "touchdowns" + SportsMarketMetricTripleDouble SportsMarketMetric = "triple_double" + SportsMarketMetricTriples SportsMarketMetric = "triples" + SportsMarketMetricTurnovers SportsMarketMetric = "turnovers" + SportsMarketMetricWalks SportsMarketMetric = "walks" + SportsMarketMetricWickets SportsMarketMetric = "wickets" + SportsMarketMetricWins SportsMarketMetric = "wins" + SportsMarketMetricYellowCards SportsMarketMetric = "yellow_cards" +) + +// Valid indicates whether the value is a known member of the SportsMarketMetric enum. +func (e SportsMarketMetric) Valid() bool { + switch e { + case SportsMarketMetricAces: + return true + case SportsMarketMetricAssists: + return true + case SportsMarketMetricBallsFaced: + return true + case SportsMarketMetricBirdies: + return true + case SportsMarketMetricBlockedShots: + return true + case SportsMarketMetricBlocks: + return true + case SportsMarketMetricBogeys: + return true + case SportsMarketMetricBoundaries: + return true + case SportsMarketMetricBreakPointsWon: + return true + case SportsMarketMetricCards: + return true + case SportsMarketMetricCatches: + return true + case SportsMarketMetricCleanSheets: + return true + case SportsMarketMetricCompletedPasses: + return true + case SportsMarketMetricControlTime: + return true + case SportsMarketMetricCorners: + return true + case SportsMarketMetricDefensiveRebounds: + return true + case SportsMarketMetricDoubleDouble: + return true + case SportsMarketMetricDoubleFaults: + return true + case SportsMarketMetricDoubles: + return true + case SportsMarketMetricEagles: + return true + case SportsMarketMetricEarnedRuns: + return true + case SportsMarketMetricErrors: + return true + case SportsMarketMetricFaceoffWins: + return true + case SportsMarketMetricFairwaysHit: + return true + case SportsMarketMetricFantasyPoints: + return true + case SportsMarketMetricFastestLap: + return true + case SportsMarketMetricFieldGoalsMade: + return true + case SportsMarketMetricFinishingPosition: + return true + case SportsMarketMetricFouls: + return true + case SportsMarketMetricFours: + return true + case SportsMarketMetricFreeThrowsMade: + return true + case SportsMarketMetricFumbles: + return true + case SportsMarketMetricGames: + return true + case SportsMarketMetricGoals: + return true + case SportsMarketMetricGoalsAllowed: + return true + case SportsMarketMetricGreensInRegulation: + return true + case SportsMarketMetricGridPosition: + return true + case SportsMarketMetricHits: + return true + case SportsMarketMetricHitsAllowed: + return true + case SportsMarketMetricHitsRunsRbis: + return true + case SportsMarketMetricHolesInOne: + return true + case SportsMarketMetricHomeRuns: + return true + case SportsMarketMetricInningsPitched: + return true + case SportsMarketMetricInterceptionsThrown: + return true + case SportsMarketMetricKickingPoints: + return true + case SportsMarketMetricKnockdowns: + return true + case SportsMarketMetricLapTime: + return true + case SportsMarketMetricLapsCompleted: + return true + case SportsMarketMetricLapsLed: + return true + case SportsMarketMetricLongestPassCompletion: + return true + case SportsMarketMetricLongestReception: + return true + case SportsMarketMetricLongestRush: + return true + case SportsMarketMetricMaidenOvers: + return true + case SportsMarketMetricOffensiveRebounds: + return true + case SportsMarketMetricOffsides: + return true + case SportsMarketMetricOther: + return true + case SportsMarketMetricPars: + return true + case SportsMarketMetricPassAttempts: + return true + case SportsMarketMetricPassCompletions: + return true + case SportsMarketMetricPasses: + return true + case SportsMarketMetricPassingTouchdowns: + return true + case SportsMarketMetricPassingYards: + return true + case SportsMarketMetricPenaltyMinutes: + return true + case SportsMarketMetricPitStops: + return true + case SportsMarketMetricPitchingOutsRecorded: + return true + case SportsMarketMetricPoints: + return true + case SportsMarketMetricPointsAssists: + return true + case SportsMarketMetricPointsRebounds: + return true + case SportsMarketMetricPointsReboundsAssists: + return true + case SportsMarketMetricPositionsGained: + return true + case SportsMarketMetricPowerPlayPoints: + return true + case SportsMarketMetricPutts: + return true + case SportsMarketMetricQualifyingPosition: + return true + case SportsMarketMetricRebounds: + return true + case SportsMarketMetricReboundsAssists: + return true + case SportsMarketMetricReceivingTouchdowns: + return true + case SportsMarketMetricReceivingYards: + return true + case SportsMarketMetricReceptions: + return true + case SportsMarketMetricRedCards: + return true + case SportsMarketMetricRetirements: + return true + case SportsMarketMetricRounds: + return true + case SportsMarketMetricRuns: + return true + case SportsMarketMetricRunsBattedIn: + return true + case SportsMarketMetricRunsConceded: + return true + case SportsMarketMetricRushAttempts: + return true + case SportsMarketMetricRushingTouchdowns: + return true + case SportsMarketMetricRushingYards: + return true + case SportsMarketMetricSacks: + return true + case SportsMarketMetricSafetyCars: + return true + case SportsMarketMetricSaves: + return true + case SportsMarketMetricSets: + return true + case SportsMarketMetricShots: + return true + case SportsMarketMetricShotsOnGoal: + return true + case SportsMarketMetricShotsOnTarget: + return true + case SportsMarketMetricShutouts: + return true + case SportsMarketMetricSignificantStrikes: + return true + case SportsMarketMetricSingles: + return true + case SportsMarketMetricSixes: + return true + case SportsMarketMetricSteals: + return true + case SportsMarketMetricStolenBases: + return true + case SportsMarketMetricStrikeouts: + return true + case SportsMarketMetricStrokes: + return true + case SportsMarketMetricSubmissionAttempts: + return true + case SportsMarketMetricTackles: + return true + case SportsMarketMetricTakedowns: + return true + case SportsMarketMetricThreePointersMade: + return true + case SportsMarketMetricTiebreaksWon: + return true + case SportsMarketMetricTotalBases: + return true + case SportsMarketMetricTotalPointsWon: + return true + case SportsMarketMetricTotalStrikes: + return true + case SportsMarketMetricTouchdowns: + return true + case SportsMarketMetricTripleDouble: + return true + case SportsMarketMetricTriples: + return true + case SportsMarketMetricTurnovers: + return true + case SportsMarketMetricWalks: + return true + case SportsMarketMetricWickets: + return true + case SportsMarketMetricWins: + return true + case SportsMarketMetricYellowCards: + return true + default: + return false + } +} + +// Defines values for SportsMarketScopeType. +const ( + SportsMarketScopeTypeCompetition SportsMarketScopeType = "competition" + SportsMarketScopeTypeFullContest SportsMarketScopeType = "full_contest" + SportsMarketScopeTypeGame SportsMarketScopeType = "game" + SportsMarketScopeTypeHalf SportsMarketScopeType = "half" + SportsMarketScopeTypeHole SportsMarketScopeType = "hole" + SportsMarketScopeTypeInning SportsMarketScopeType = "inning" + SportsMarketScopeTypeLap SportsMarketScopeType = "lap" + SportsMarketScopeTypeMatchDay SportsMarketScopeType = "match_day" + SportsMarketScopeTypeOther SportsMarketScopeType = "other" + SportsMarketScopeTypeOver SportsMarketScopeType = "over" + SportsMarketScopeTypePeriod SportsMarketScopeType = "period" + SportsMarketScopeTypePowerplay SportsMarketScopeType = "powerplay" + SportsMarketScopeTypePractice SportsMarketScopeType = "practice" + SportsMarketScopeTypeQualifying SportsMarketScopeType = "qualifying" + SportsMarketScopeTypeQuarter SportsMarketScopeType = "quarter" + SportsMarketScopeTypeRace SportsMarketScopeType = "race" + SportsMarketScopeTypeRegulation SportsMarketScopeType = "regulation" + SportsMarketScopeTypeRound SportsMarketScopeType = "round" + SportsMarketScopeTypeSeason SportsMarketScopeType = "season" + SportsMarketScopeTypeSeries SportsMarketScopeType = "series" + SportsMarketScopeTypeSession SportsMarketScopeType = "session" + SportsMarketScopeTypeSet SportsMarketScopeType = "set" + SportsMarketScopeTypeSprint SportsMarketScopeType = "sprint" + SportsMarketScopeTypeStage SportsMarketScopeType = "stage" + SportsMarketScopeTypeSuperOver SportsMarketScopeType = "super_over" + SportsMarketScopeTypeTeamInnings SportsMarketScopeType = "team_innings" + SportsMarketScopeTypeTournament SportsMarketScopeType = "tournament" +) + +// Valid indicates whether the value is a known member of the SportsMarketScopeType enum. +func (e SportsMarketScopeType) Valid() bool { + switch e { + case SportsMarketScopeTypeCompetition: + return true + case SportsMarketScopeTypeFullContest: + return true + case SportsMarketScopeTypeGame: + return true + case SportsMarketScopeTypeHalf: + return true + case SportsMarketScopeTypeHole: + return true + case SportsMarketScopeTypeInning: + return true + case SportsMarketScopeTypeLap: + return true + case SportsMarketScopeTypeMatchDay: + return true + case SportsMarketScopeTypeOther: + return true + case SportsMarketScopeTypeOver: + return true + case SportsMarketScopeTypePeriod: + return true + case SportsMarketScopeTypePowerplay: + return true + case SportsMarketScopeTypePractice: + return true + case SportsMarketScopeTypeQualifying: + return true + case SportsMarketScopeTypeQuarter: + return true + case SportsMarketScopeTypeRace: + return true + case SportsMarketScopeTypeRegulation: + return true + case SportsMarketScopeTypeRound: + return true + case SportsMarketScopeTypeSeason: + return true + case SportsMarketScopeTypeSeries: + return true + case SportsMarketScopeTypeSession: + return true + case SportsMarketScopeTypeSet: + return true + case SportsMarketScopeTypeSprint: + return true + case SportsMarketScopeTypeStage: + return true + case SportsMarketScopeTypeSuperOver: + return true + case SportsMarketScopeTypeTeamInnings: + return true + case SportsMarketScopeTypeTournament: + return true + default: + return false + } +} + +// Defines values for SportsMarketSport. +const ( + AmericanFootball SportsMarketSport = "american_football" + Athletics SportsMarketSport = "athletics" + AustralianRulesFootball SportsMarketSport = "australian_rules_football" + Baseball SportsMarketSport = "baseball" + Basketball SportsMarketSport = "basketball" + Boxing SportsMarketSport = "boxing" + Chess SportsMarketSport = "chess" + Cricket SportsMarketSport = "cricket" + Cycling SportsMarketSport = "cycling" + Darts SportsMarketSport = "darts" + Esports SportsMarketSport = "esports" + Golf SportsMarketSport = "golf" + Hockey SportsMarketSport = "hockey" + Lacrosse SportsMarketSport = "lacrosse" + MixedMartialArts SportsMarketSport = "mixed_martial_arts" + Motorsports SportsMarketSport = "motorsports" + Rugby SportsMarketSport = "rugby" + Sailing SportsMarketSport = "sailing" + Soccer SportsMarketSport = "soccer" + Tennis SportsMarketSport = "tennis" +) + +// Valid indicates whether the value is a known member of the SportsMarketSport enum. +func (e SportsMarketSport) Valid() bool { + switch e { + case AmericanFootball: + return true + case Athletics: + return true + case AustralianRulesFootball: + return true + case Baseball: + return true + case Basketball: + return true + case Boxing: + return true + case Chess: + return true + case Cricket: + return true + case Cycling: + return true + case Darts: + return true + case Esports: + return true + case Golf: + return true + case Hockey: + return true + case Lacrosse: + return true + case MixedMartialArts: + return true + case Motorsports: + return true + case Rugby: + return true + case Sailing: + return true + case Soccer: + return true + case Tennis: + return true + default: + return false + } +} + +// Defines values for SportsMarketSubject. +const ( + SportsMarketSubjectContest SportsMarketSubject = "contest" + SportsMarketSubjectOther SportsMarketSubject = "other" + SportsMarketSubjectParticipant SportsMarketSubject = "participant" + SportsMarketSubjectPlayer SportsMarketSubject = "player" + SportsMarketSubjectTeam SportsMarketSubject = "team" +) + +// Valid indicates whether the value is a known member of the SportsMarketSubject enum. +func (e SportsMarketSubject) Valid() bool { + switch e { + case SportsMarketSubjectContest: + return true + case SportsMarketSubjectOther: + return true + case SportsMarketSubjectParticipant: + return true + case SportsMarketSubjectPlayer: + return true + case SportsMarketSubjectTeam: + return true + default: + return false + } +} + +// Defines values for SportsMarketType. +const ( + SportsMarketTypeCorrectScore SportsMarketType = "correct_score" + SportsMarketTypeFutures SportsMarketType = "futures" + SportsMarketTypeMoneyline SportsMarketType = "moneyline" + SportsMarketTypeOther SportsMarketType = "other" + SportsMarketTypeProp SportsMarketType = "prop" + SportsMarketTypeSpread SportsMarketType = "spread" + SportsMarketTypeToAdvance SportsMarketType = "to_advance" + SportsMarketTypeTotal SportsMarketType = "total" +) + +// Valid indicates whether the value is a known member of the SportsMarketType enum. +func (e SportsMarketType) Valid() bool { + switch e { + case SportsMarketTypeCorrectScore: + return true + case SportsMarketTypeFutures: + return true + case SportsMarketTypeMoneyline: + return true + case SportsMarketTypeOther: + return true + case SportsMarketTypeProp: + return true + case SportsMarketTypeSpread: + return true + case SportsMarketTypeToAdvance: + return true + case SportsMarketTypeTotal: + return true + default: + return false + } +} + +// Defines values for StrikeType. +const ( + Above StrikeType = "above" + Over StrikeType = "over" + OverOrEqual StrikeType = "over_or_equal" + Reference StrikeType = "reference" + Spread StrikeType = "spread" + Under StrikeType = "under" + UnderOrEqual StrikeType = "under_or_equal" +) + +// Valid indicates whether the value is a known member of the StrikeType enum. +func (e StrikeType) Valid() bool { + switch e { + case Above: + return true + case Over: + return true + case OverOrEqual: + return true + case Reference: + return true + case Spread: + return true + case Under: + return true + case UnderOrEqual: + return true + default: + return false + } +} + +// Defines values for TermsNotAcceptedErrorError. +const ( + TERMSNOTACCEPTED TermsNotAcceptedErrorError = "TERMS_NOT_ACCEPTED" +) + +// Valid indicates whether the value is a known member of the TermsNotAcceptedErrorError enum. +func (e TermsNotAcceptedErrorError) Valid() bool { + switch e { + case TERMSNOTACCEPTED: + return true + default: + return false + } +} + +// Defines values for TermsNotAcceptedErrorMessage. +const ( + PredictionMarketsTermsMustBeAcceptedBeforePlacingOrders TermsNotAcceptedErrorMessage = "Prediction markets terms must be accepted before placing orders" +) + +// Valid indicates whether the value is a known member of the TermsNotAcceptedErrorMessage enum. +func (e TermsNotAcceptedErrorMessage) Valid() bool { + switch e { + case PredictionMarketsTermsMustBeAcceptedBeforePlacingOrders: + return true + default: + return false + } +} + +// Defines values for TimeInForce. +const ( + TimeInForceFillOrKill TimeInForce = "fill-or-kill" + TimeInForceGoodTilCancel TimeInForce = "good-til-cancel" + TimeInForceImmediateOrCancel TimeInForce = "immediate-or-cancel" +) + +// Valid indicates whether the value is a known member of the TimeInForce enum. +func (e TimeInForce) Valid() bool { + switch e { + case TimeInForceFillOrKill: + return true + case TimeInForceGoodTilCancel: + return true + case TimeInForceImmediateOrCancel: + return true + default: + return false + } +} + +// Defines values for ListLiquidityRewardsEventsParamsSort. +const ( + CategoryAsc ListLiquidityRewardsEventsParamsSort = "category_asc" + CategoryDesc ListLiquidityRewardsEventsParamsSort = "category_desc" + CompetitionAsc ListLiquidityRewardsEventsParamsSort = "competition_asc" + CompetitionDesc ListLiquidityRewardsEventsParamsSort = "competition_desc" + DailyPoolAsc ListLiquidityRewardsEventsParamsSort = "daily_pool_asc" + DailyPoolDesc ListLiquidityRewardsEventsParamsSort = "daily_pool_desc" + EndsLatest ListLiquidityRewardsEventsParamsSort = "ends_latest" + EndsSoonest ListLiquidityRewardsEventsParamsSort = "ends_soonest" + TitleAsc ListLiquidityRewardsEventsParamsSort = "title_asc" + TitleDesc ListLiquidityRewardsEventsParamsSort = "title_desc" +) + +// Valid indicates whether the value is a known member of the ListLiquidityRewardsEventsParamsSort enum. +func (e ListLiquidityRewardsEventsParamsSort) Valid() bool { + switch e { + case CategoryAsc: + return true + case CategoryDesc: + return true + case CompetitionAsc: + return true + case CompetitionDesc: + return true + case DailyPoolAsc: + return true + case DailyPoolDesc: + return true + case EndsLatest: + return true + case EndsSoonest: + return true + case TitleAsc: + return true + case TitleDesc: + return true + default: + return false + } +} + +// Defines values for GetOrderHistoryJSONBodyStatus. +const ( + GetOrderHistoryJSONBodyStatusCancelled GetOrderHistoryJSONBodyStatus = "cancelled" + GetOrderHistoryJSONBodyStatusFilled GetOrderHistoryJSONBodyStatus = "filled" +) + +// Valid indicates whether the value is a known member of the GetOrderHistoryJSONBodyStatus enum. +func (e GetOrderHistoryJSONBodyStatus) Valid() bool { + switch e { + case GetOrderHistoryJSONBodyStatusCancelled: + return true + case GetOrderHistoryJSONBodyStatusFilled: + return true + default: + return false + } +} + +// Defines values for GetPositionsParamsSort. +const ( + ExpiryDate GetPositionsParamsSort = "expiryDate" + MinusExpiryDate GetPositionsParamsSort = "-expiryDate" + MinusPositionValue GetPositionsParamsSort = "-positionValue" + MinusUnrealizedPnl GetPositionsParamsSort = "-unrealizedPnl" + PlusExpiryDate GetPositionsParamsSort = "+expiryDate" + PlusPositionValue GetPositionsParamsSort = "+positionValue" + PlusUnrealizedPnl GetPositionsParamsSort = "+unrealizedPnl" + PositionValue GetPositionsParamsSort = "positionValue" + UnrealizedPnl GetPositionsParamsSort = "unrealizedPnl" +) + +// Valid indicates whether the value is a known member of the GetPositionsParamsSort enum. +func (e GetPositionsParamsSort) Valid() bool { + switch e { + case ExpiryDate: + return true + case MinusExpiryDate: + return true + case MinusPositionValue: + return true + case MinusUnrealizedPnl: + return true + case PlusExpiryDate: + return true + case PlusPositionValue: + return true + case PlusUnrealizedPnl: + return true + case PositionValue: + return true + case UnrealizedPnl: + return true + default: + return false + } +} + +// Defines values for GetSettledPositionsParamsSort. +const ( + Date GetSettledPositionsParamsSort = "date" + MinusDate GetSettledPositionsParamsSort = "-date" + MinusPayout GetSettledPositionsParamsSort = "-payout" + Payout GetSettledPositionsParamsSort = "payout" + PlusPayout GetSettledPositionsParamsSort = "+payout" +) + +// Valid indicates whether the value is a known member of the GetSettledPositionsParamsSort enum. +func (e GetSettledPositionsParamsSort) Valid() bool { + switch e { + case Date: + return true + case MinusDate: + return true + case MinusPayout: + return true + case Payout: + return true + case PlusPayout: + return true + default: + return false + } +} + +// AcceptPredictionMarketsTermsResponse defines model for AcceptPredictionMarketsTermsResponse. +type AcceptPredictionMarketsTermsResponse struct { + Success bool `json:"success"` +} + +// AccountGroupBlockedError defines model for AccountGroupBlockedError. +type AccountGroupBlockedError struct { + Code AccountGroupBlockedErrorCode `json:"code"` + Error AccountGroupBlockedErrorError `json:"error"` +} + +// AccountGroupBlockedErrorCode defines model for AccountGroupBlockedError.Code. +type AccountGroupBlockedErrorCode string + +// AccountGroupBlockedErrorError defines model for AccountGroupBlockedError.Error. +type AccountGroupBlockedErrorError string + +// AuthErrorResponse defines model for AuthErrorResponse. +type AuthErrorResponse struct { + // Message Human-readable authentication or authorization detail + Message string `json:"message"` + + // Reason Authentication or authorization error class + Reason string `json:"reason"` + Result AuthErrorResponseResult `json:"result"` +} + +// AuthErrorResponseResult defines model for AuthErrorResponse.Result. +type AuthErrorResponseResult string + +// BatchOrderResponse An accepted order returned for one batch entry. +type BatchOrderResponse struct { + // AvgExecutionPrice Average price of fills; omitted when unavailable + AvgExecutionPrice *string `json:"avgExecutionPrice,omitempty"` + + // CancelledAt Cancellation time; omitted unless the order was cancelled + CancelledAt *time.Time `json:"cancelledAt,omitempty"` + + // ClientOrderId Client-provided order ID; omitted when unavailable + ClientOrderId *string `json:"clientOrderId,omitempty"` + ContractMetadata *ContractMetadata `json:"contractMetadata,omitempty"` + CreatedAt time.Time `json:"createdAt"` + + // FilledQuantity Amount filled so far + FilledQuantity string `json:"filledQuantity"` + + // FundsOnHold Cash reserved for the unfilled portion of a resting buy order; omitted when unavailable + FundsOnHold *string `json:"fundsOnHold,omitempty"` + + // GlobalOrderId Global order ID; omitted when unavailable + GlobalOrderId *string `json:"globalOrderId,omitempty"` + + // HashOrderId Hashed order ID; omitted when unavailable + HashOrderId *string `json:"hashOrderId,omitempty"` + OrderId int64 `json:"orderId"` + + // OrderType Order type. `stop-limit` orders require a `stopPrice` that triggers a limit order at `price` when the market reaches the trigger. + OrderType OrderType `json:"orderType"` + + // Outcome The outcome being traded (Yes or No) + Outcome Outcome `json:"outcome"` + + // Price Limit price + Price string `json:"price"` + + // PromoCashApplied Promotional cash reserved or applied to the order; omitted when unavailable + PromoCashApplied *string `json:"promoCashApplied,omitempty"` + + // Quantity Original order quantity + Quantity string `json:"quantity"` + + // RemainingQuantity Amount remaining to fill + RemainingQuantity string `json:"remainingQuantity"` + Side OrderSide `json:"side"` + Status BatchOrderResponseStatus `json:"status"` + + // StopPrice Stop trigger price; omitted unless populated for a `stop-limit` order + StopPrice *string `json:"stopPrice,omitempty"` + Symbol string `json:"symbol"` + TimeInForce BatchOrderResponseTimeInForce `json:"timeInForce"` + UpdatedAt time.Time `json:"updatedAt"` +} + +// BatchOrderResponseStatus defines model for BatchOrderResponse.Status. +type BatchOrderResponseStatus string + +// BatchOrderResponseTimeInForce defines model for BatchOrderResponse.TimeInForce. +type BatchOrderResponseTimeInForce string + +// CancelOrderBatchErrorResult defines model for CancelOrderBatchErrorResult. +type CancelOrderBatchErrorResult struct { + // Error Error class for a rejected cancellation + Error string `json:"error"` + + // Message Human-readable detail for a rejected cancellation + Message string `json:"message"` + + // OrderId Order ID from the corresponding request entry. + OrderId int64 `json:"orderId"` +} + +// CancelOrderBatchRequest defines model for CancelOrderBatchRequest. +type CancelOrderBatchRequest struct { + // OrderIds Order IDs to cancel. Each ID may be an integer or a quoted numeric string. All IDs are validated before any cancellation is attempted. + OrderIds []CancelOrderBatchRequest_OrderIds_Item `json:"orderIds"` +} + +// CancelOrderBatchRequestOrderIds0 defines model for . +type CancelOrderBatchRequestOrderIds0 = int64 + +// CancelOrderBatchRequestOrderIds1 defines model for . +type CancelOrderBatchRequestOrderIds1 = string + +// CancelOrderBatchRequest_OrderIds_Item defines model for CancelOrderBatchRequest.orderIds.Item. +type CancelOrderBatchRequest_OrderIds_Item struct { + union json.RawMessage +} + +// CancelOrderBatchResponse defines model for CancelOrderBatchResponse. +type CancelOrderBatchResponse struct { + // Results One result for each requested cancellation, in request order. + Results []CancelOrderBatchResult `json:"results"` +} + +// CancelOrderBatchResult Exactly one outcome is present. Successful entries contain `orderId` and `result`; rejected entries contain `orderId`, `error`, and `message`. +type CancelOrderBatchResult struct { + union json.RawMessage +} + +// CancelOrderBatchSuccessResult defines model for CancelOrderBatchSuccessResult. +type CancelOrderBatchSuccessResult struct { + // OrderId Order ID from the corresponding request entry. + OrderId int64 `json:"orderId"` + Result CancelOrderBatchSuccessResultResult `json:"result"` +} + +// CancelOrderBatchSuccessResultResult defines model for CancelOrderBatchSuccessResult.Result. +type CancelOrderBatchSuccessResultResult string + +// CashedOutPosition A qualifying cash-out (early sell before contract resolution) with cost-basis context. Exposed only via the `withCashOuts=true` sibling array on `POST /v1/prediction-markets/positions/settled`. Distinct from `SettledPosition` — cash-outs don't have a `payout` or `resolutionSide` since the contract hadn't resolved when the user sold. +type CashedOutPosition struct { + // AccountId Account that held the position. + AccountId int64 `json:"accountId"` + ContractMetadata *ContractMetadata `json:"contractMetadata,omitempty"` + + // CostBasis Cost basis allocated proportionally to the filled quantity (`(costBasisSpend / costBasisPositionBalance) * filledQuantity`). + CostBasis string `json:"costBasis"` + + // FilledQuantity Quantity sold (cumulative filled quantity on the cash-out order). + FilledQuantity string `json:"filledQuantity"` + + // InstrumentId Contract instrument ID. + InstrumentId int64 `json:"instrumentId"` + + // InstrumentSymbol Contract instrument symbol. + InstrumentSymbol string `json:"instrumentSymbol"` + + // NetProfit Realized P&L from this cash-out fill (`proceeds - costBasis`). Equals the ledger `realized_pl` delta on the position-balance row pair around the fill; falls back to `0` under transient market-data lag so a missing post-fill snapshot can't poison the page. + NetProfit string `json:"netProfit"` + + // Proceeds Amount received from the sale in USD. For prediction sells, proceeds flow through `cash_balance` rather than `closed_orders.total_spend`, so the value is derived from position-balance snapshots before/after the fill. + Proceeds string `json:"proceeds"` + + // Side Always `sell` for cash-outs. + Side CashedOutPositionSide `json:"side"` + + // Timestamp Wall-clock timestamp when the cash-out order closed (ISO 8601). + Timestamp time.Time `json:"timestamp"` +} + +// CashedOutPositionSide Always `sell` for cash-outs. +type CashedOutPositionSide string + +// ComboLeg defines model for ComboLeg. +type ComboLeg struct { + // ComboId Internal ID of the parent combo contract + ComboId int64 `json:"comboId"` + + // Contract Full metadata for the underlying single contract + Contract *ContractMetadata `json:"contract,omitempty"` + + // ContractId Internal ID of the underlying single contract, represented as a decimal string + ContractId string `json:"contractId"` + + // LegIndex Zero-based position of this leg in the combo + LegIndex int `json:"legIndex"` + + // LegOutcome The outcome this leg has settled to, if resolved (`"Yes"` or `"No"`). Null while the leg is still active. + LegOutcome *string `json:"legOutcome,omitempty"` + + // RequiredOutcome The outcome this leg must settle for the combo to settle YES + RequiredOutcome ComboLegRequiredOutcome `json:"requiredOutcome"` + + // ResolvedAt UTC timestamp when this leg resolved. Null while still active. + ResolvedAt *time.Time `json:"resolvedAt,omitempty"` +} + +// ComboLegRequiredOutcome The outcome this leg must settle for the combo to settle YES +type ComboLegRequiredOutcome string + +// ComboResponse defines model for ComboResponse. +type ComboResponse struct { + // Contract Metadata for the combo contract itself (ticker, status, expiry, etc.) + Contract ContractMetadata `json:"contract"` + + // Legs Ordered list of legs that make up this combo + Legs []ComboLeg `json:"legs"` +} + +// ComboSummary defines model for ComboSummary. +type ComboSummary struct { + // CanonicalLegKey Canonical identity of the complete combo leg set. + CanonicalLegKey string `json:"canonicalLegKey"` + + // CreatedAt Creation time, when available. + CreatedAt *time.Time `json:"createdAt,omitempty"` + + // DisplayName Human-readable combo name, when available. + DisplayName *string `json:"displayName,omitempty"` + + // Id Internal combo ID. + Id int64 `json:"id"` + + // InstrumentId Associated instrument ID, when available. + InstrumentId *int64 `json:"instrumentId,omitempty"` + + // InstrumentRegistered Whether the combo has been registered with an instrument symbol. + InstrumentRegistered bool `json:"instrumentRegistered"` + + // InstrumentSymbol Associated instrument symbol, when available. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // LatestExpiryDate Latest expiry among the underlying legs, when available. + LatestExpiryDate *time.Time `json:"latestExpiryDate,omitempty"` + + // LegCount Number of legs in the combo. + LegCount int32 `json:"legCount"` + + // Legs Canonically ordered combo legs. + Legs []ComboSummaryLeg `json:"legs"` + + // Status Current combo status, when available. + Status *string `json:"status,omitempty"` + + // UpdatedAt Most recent update time, when available. + UpdatedAt *time.Time `json:"updatedAt,omitempty"` +} + +// ComboSummaryLeg defines model for ComboSummaryLeg. +type ComboSummaryLeg struct { + // ComboId Parent combo ID. + ComboId int64 `json:"comboId"` + + // Contract Underlying contract metadata, when available. + Contract *ContractMetadata `json:"contract,omitempty"` + + // ContractId Underlying contract ID as a decimal string. + ContractId string `json:"contractId"` + + // LegIndex Zero-based leg position in canonical order. + LegIndex int32 `json:"legIndex"` + + // LegOutcome Settled outcome for the leg, when resolved. + LegOutcome *ComboSummaryLegLegOutcome `json:"legOutcome,omitempty"` + + // RequiredOutcome Required settlement outcome for the leg. + RequiredOutcome ComboSummaryLegRequiredOutcome `json:"requiredOutcome"` + + // ResolvedAt Resolution time for the leg, when resolved. + ResolvedAt *time.Time `json:"resolvedAt,omitempty"` +} + +// ComboSummaryLegLegOutcome Settled outcome for the leg, when resolved. +type ComboSummaryLegLegOutcome string + +// ComboSummaryLegRequiredOutcome Required settlement outcome for the leg. +type ComboSummaryLegRequiredOutcome string + +// ComboWriteError defines model for ComboWriteError. +type ComboWriteError struct { + // Code Machine-readable code for validation or missing-leg errors, when available. + Code *string `json:"code,omitempty"` + + // Error Error class. + Error string `json:"error"` + + // Message Human-readable error detail. + Message string `json:"message"` +} + +// Contract Contract quantity and price validation is instrument-specific. Clients must validate order quantities and prices against the returned increment and minimum fields rather than assuming a fixed grid. +type Contract struct { + // AbbreviatedName Short form label (e.g., ">$90") + AbbreviatedName *string `json:"abbreviatedName,omitempty"` + Color *string `json:"color,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + + // Description Rich text description + Description *map[string]interface{} `json:"description,omitempty"` + EffectiveDate *time.Time `json:"effectiveDate,omitempty"` + ExpiryDate *time.Time `json:"expiryDate,omitempty"` + Id *string `json:"id,omitempty"` + ImageUrl *string `json:"imageUrl,omitempty"` + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Label Human-readable label for the contract's YES-space proposition (e.g., "SOL > $90") + Label *string `json:"label,omitempty"` + + // MarketState Trading state of the contract + MarketState *ContractMarketState `json:"marketState,omitempty"` + PriceHistory *[]PricePoint `json:"priceHistory,omitempty"` + + // PriceIncrement Contract price grid from instrument refdata (for example, "0.0001"). + PriceIncrement *string `json:"priceIncrement,omitempty"` + + // PriceMinimum Minimum contract price and anchor for the instrument price grid (for example, "0.0001"). + PriceMinimum *string `json:"priceMinimum,omitempty"` + + // Prices Current bid/ask pricing for the contract + Prices *ContractPrices `json:"prices,omitempty"` + + // QuantityIncrement Contract quantity grid from instrument refdata (for example, "0.01"). + QuantityIncrement *string `json:"quantityIncrement,omitempty"` + + // QuantityMinimum Minimum contract quantity from instrument refdata (for example, "1.00"). + QuantityMinimum *string `json:"quantityMinimum,omitempty"` + + // QuoteAssetPrecision Decimal places supported by the instrument's quote asset. + QuoteAssetPrecision *int `json:"quoteAssetPrecision,omitempty"` + + // ResolutionSide The outcome being traded (Yes or No) + ResolutionSide *Outcome `json:"resolutionSide,omitempty"` + ResolvedAt *time.Time `json:"resolvedAt,omitempty"` + + // SettlementValue The observed settlement price. Only present after the contract is settled. + SettlementValue *string `json:"settlementValue,omitempty"` + + // SortOrder Display order within the event + SortOrder *int `json:"sortOrder,omitempty"` + + // Source Deprecated: use the event-level `sourceDetails` (`agency` + `index`) instead. Data source identifier for price observation (e.g., "GRR-KAIKO_BTCUSD_60S"). Present for crypto Up/Down contracts. + // Deprecated: this property has been marked as deprecated upstream, but no `x-deprecated-reason` was set + Source *string `json:"source,omitempty"` + + // Status Status of a prediction market + Status *MarketStatus `json:"status,omitempty"` + + // Strike Strike price or contract threshold information for Up/Down crypto contracts and sports prediction market contracts. + Strike *Strike `json:"strike,omitempty"` + TermsAndConditionsUrl *string `json:"termsAndConditionsUrl,omitempty"` + Ticker *string `json:"ticker,omitempty"` + TotalShares *string `json:"totalShares,omitempty"` +} + +// ContractMarketState Trading state of the contract +type ContractMarketState string + +// ContractMetadata defines model for ContractMetadata. +type ContractMetadata struct { + Category *string `json:"category,omitempty"` + ContractId *string `json:"contractId,omitempty"` + ContractName *string `json:"contractName,omitempty"` + ContractStatus *string `json:"contractStatus,omitempty"` + ContractTicker *string `json:"contractTicker,omitempty"` + EventName *string `json:"eventName,omitempty"` + EventTicker *string `json:"eventTicker,omitempty"` + + // EventType Event type ("binary" or "categorical") + EventType *string `json:"eventType,omitempty"` + ExpiryDate *time.Time `json:"expiryDate,omitempty"` + + // ParentEventTicker Parent event ticker for sub-events + ParentEventTicker *string `json:"parentEventTicker,omitempty"` + + // ResolutionSide Winning outcome if resolved ("yes" or "no") + ResolutionSide *string `json:"resolutionSide,omitempty"` + ResolvedAt *time.Time `json:"resolvedAt,omitempty"` + + // StartTime Start datetime (ISO 8601) + StartTime *time.Time `json:"startTime,omitempty"` +} + +// ContractPrices Current bid/ask pricing for the contract +type ContractPrices struct { + // BestAsk Lowest sell offer + BestAsk *string `json:"bestAsk,omitempty"` + + // BestBid Highest buy offer + BestBid *string `json:"bestBid,omitempty"` + + // Buy Buy prices for each outcome + Buy *struct { + // No Price to buy NO outcome + No *string `json:"no,omitempty"` + + // Yes Price to buy YES outcome + Yes *string `json:"yes,omitempty"` + } `json:"buy,omitempty"` + + // LastTradePrice Most recent transaction price + LastTradePrice *string `json:"lastTradePrice,omitempty"` + + // Sell Sell prices for each outcome + Sell *struct { + // No Price to sell NO outcome + No *string `json:"no,omitempty"` + + // Yes Price to sell YES outcome + Yes *string `json:"yes,omitempty"` + } `json:"sell,omitempty"` +} + +// ContractShareVolume defines model for ContractShareVolume. +type ContractShareVolume struct { + // Symbol Contract instrument symbol + Symbol *string `json:"symbol,omitempty"` + + // TotalQty Total taker volume across all participants (in shares) + TotalQty *string `json:"totalQty,omitempty"` + + // UserAggressorQty The authenticated user's taker (aggressor) volume (in shares) + UserAggressorQty *string `json:"userAggressorQty,omitempty"` + + // UserRestingQty The authenticated user's maker (resting) volume (in shares) + UserRestingQty *string `json:"userRestingQty,omitempty"` +} + +// CreateComboLeg defines model for CreateComboLeg. +type CreateComboLeg struct { + // ContractId Underlying contract ID as a decimal string. + ContractId string `json:"contractId"` + + // RequiredOutcome Required settlement outcome for this leg. + RequiredOutcome CreateComboLegRequiredOutcome `json:"requiredOutcome"` +} + +// CreateComboLegRequiredOutcome Required settlement outcome for this leg. +type CreateComboLegRequiredOutcome string + +// CreateComboRequest A canonical combo definition. The authenticated account is derived from the signed request and is not a request field. +type CreateComboRequest struct { + // Legs Two to six distinct underlying contract legs. The service canonicalizes their complete set, so leg order does not create a distinct combo. + Legs []CreateComboLeg `json:"legs"` +} + +// CreateComboResponse defines model for CreateComboResponse. +type CreateComboResponse struct { + // AlreadyExisted `false` when this request created the canonical combo; `true` when the canonical combo already existed. + AlreadyExisted bool `json:"alreadyExisted"` + Combo ComboSummary `json:"combo"` +} + +// Error defines model for Error. +type Error struct { + // Error Error code + Error *string `json:"error,omitempty"` + + // Message Human-readable error message + Message *string `json:"message,omitempty"` +} + +// Event A prediction market event containing one or more tradeable contracts +type Event struct { + Category *string `json:"category,omitempty"` + ContractOrderbooks *map[string]OrderBook `json:"contractOrderbooks,omitempty"` + + // Contracts Tradeable contracts within this event + Contracts *[]Contract `json:"contracts,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + Description *string `json:"description,omitempty"` + EffectiveDate *time.Time `json:"effectiveDate,omitempty"` + ExpiryDate *time.Time `json:"expiryDate,omitempty"` + Id *string `json:"id,omitempty"` + ImageUrl *string `json:"imageUrl,omitempty"` + + // Liquidity Total liquidity in USD + Liquidity *string `json:"liquidity,omitempty"` + ResolvedAt *time.Time `json:"resolvedAt,omitempty"` + Series *string `json:"series,omitempty"` + + // Settlement Settlement information for resolved events + Settlement *Settlement `json:"settlement,omitempty"` + Slug *string `json:"slug,omitempty"` + + // Source Deprecated: use `sourceDetails` (`agency` + `index`) instead. Data source identifier for price observation. Aggregated from contracts for crypto Up/Down events. + // Deprecated: this property has been marked as deprecated upstream, but no `x-deprecated-reason` was set + Source *string `json:"source,omitempty"` + + // SourceDetails Structured data source information for price observation. Replaces the deprecated flat `source` string on the event and contract. Present for crypto Up/Down events. Both fields are omitted when not available. + SourceDetails *SourceDetails `json:"sourceDetails,omitempty"` + + // SportsMarket Atomic sports-market classification shared by every contract grouped under the event. Present only for sports events. All fields except `metric` are required together. + SportsMarket *SportsMarket `json:"sportsMarket,omitempty"` + + // Status Status of a prediction market + Status *MarketStatus `json:"status,omitempty"` + + // Subcategory Nested category information for the event + Subcategory *Subcategory `json:"subcategory,omitempty"` + Tags *[]string `json:"tags,omitempty"` + + // Ticker The event ticker (e.g., "BTC100K2028") + Ticker *string `json:"ticker,omitempty"` + Title *string `json:"title,omitempty"` + + // Type Type of prediction market + Type *MarketType `json:"type,omitempty"` + + // Volume Total trading volume in USD + Volume *string `json:"volume,omitempty"` +} + +// EventsResponse defines model for EventsResponse. +type EventsResponse struct { + Data *[]Event `json:"data,omitempty"` + Pagination *Pagination `json:"pagination,omitempty"` +} + +// LiquidityDailySummary defines model for LiquidityDailySummary. +type LiquidityDailySummary struct { + // Events Per-event score breakdown showing how the day's total was distributed. + Events []LiquidityEventScore `json:"events"` + + // PaidAt ISO-8601 timestamp the day's payout was credited. Always present; `null` if not yet paid. + PaidAt *time.Time `json:"paid_at"` + + // PayoutDate Date the payout applies to (Eastern Time). + PayoutDate openapi_types.Date `json:"payout_date"` + + // PayoutStatus Status of the day's payout (e.g. `PENDING`, `PAID`, `ZERO_AMOUNT`). + PayoutStatus string `json:"payout_status"` + + // TotalRewardUsd Total USD reward for the day across all events the account scored on. + TotalRewardUsd string `json:"total_reward_usd"` +} + +// LiquidityEventScore defines model for LiquidityEventScore. +type LiquidityEventScore struct { + // CategoryName Market category. + CategoryName string `json:"category_name"` + + // EventId Stable event identifier. + EventId int64 `json:"event_id"` + + // EventName Event title. + EventName string `json:"event_name"` + + // EventRewardUsd Portion of the day's total reward attributed to this event. + EventRewardUsd string `json:"event_reward_usd"` + + // NormalizedScore This account's normalized score for the event on the scoring date (0-1 range as a decimal string). + NormalizedScore string `json:"normalized_score"` + + // SnapshotCount Number of snapshots in which this account had a qualifying quote. + SnapshotCount int32 `json:"snapshot_count"` + + // TotalSnapshots Total snapshots taken for the event on the scoring date. + TotalSnapshots int32 `json:"total_snapshots"` +} + +// LiquidityRewardEvent defines model for LiquidityRewardEvent. +type LiquidityRewardEvent struct { + // Category Market category. + Category string `json:"category"` + + // DailyPoolUsd Daily USD reward pool budgeted for this event. + DailyPoolUsd string `json:"daily_pool_usd"` + + // EndsAt ISO-8601 timestamp at which the event ends and stops scoring. `null` when the underlying event has no end timestamp set. + EndsAt *time.Time `json:"ends_at"` + + // EventTicker Event ticker (e.g. `BTC2605202100`). + EventTicker string `json:"event_ticker"` + + // IconUrl Optional URL for the event icon. Omitted when not configured. + IconUrl *string `json:"icon_url,omitempty"` + + // PoolSource Whether the pool came from a per-event override or the category default. + PoolSource LiquidityRewardEventPoolSource `json:"pool_source"` + + // QualifyingMakerCount Number of accounts that met qualifying-maker criteria in the most recent snapshot window for this event. + QualifyingMakerCount int32 `json:"qualifying_maker_count"` + + // Title Event title. + Title string `json:"title"` +} + +// LiquidityRewardEventPoolSource Whether the pool came from a per-event override or the category default. +type LiquidityRewardEventPoolSource string + +// LiquidityRewardsConfig defines model for LiquidityRewardsConfig. +type LiquidityRewardsConfig struct { + // Enabled True when the program is fully configured upstream. When false, the response collapses to `{ "enabled": false }` only. + Enabled bool `json:"enabled"` + + // MaxSpreadCents Quotes wider than this spread score zero in the scoring algorithm. Only present when `enabled` is `true`. + MaxSpreadCents *int32 `json:"max_spread_cents,omitempty"` + + // MinPayoutThresholdUsd Daily reward amounts below this threshold are suppressed (sub-threshold accounts get no row at all). Only present when `enabled` is `true`. + MinPayoutThresholdUsd *string `json:"min_payout_threshold_usd,omitempty"` +} + +// LiquidityRewardsDailySummaryResponse defines model for LiquidityRewardsDailySummaryResponse. +type LiquidityRewardsDailySummaryResponse struct { + DailySummaries []LiquidityDailySummary `json:"daily_summaries"` +} + +// LiquidityRewardsEventsResponse defines model for LiquidityRewardsEventsResponse. +type LiquidityRewardsEventsResponse struct { + Events []LiquidityRewardEvent `json:"events"` + + // LastScoreDate Most recent date for which scoring has been written. `null` when no scoring has run yet. + LastScoreDate *openapi_types.Date `json:"last_score_date"` + Pagination Pagination `json:"pagination"` +} + +// LiquidityRewardsLifetimeSummary defines model for LiquidityRewardsLifetimeSummary. +type LiquidityRewardsLifetimeSummary struct { + // FirstPayoutDate Date of the earliest payout in the window, or `null` if no payouts exist. + FirstPayoutDate *openapi_types.Date `json:"first_payout_date"` + + // LastPayoutDate Date of the most recent payout in the window, or `null` if no payouts exist. + LastPayoutDate *openapi_types.Date `json:"last_payout_date"` + + // PayoutCount Number of daily payouts in the window. Always present; `0` when no payouts exist in the window. + PayoutCount int32 `json:"payout_count"` + + // TotalEarnedUsd Sum of `total_reward_usd` across daily payouts in the window. + TotalEarnedUsd string `json:"total_earned_usd"` +} + +// ListCombosResponse defines model for ListCombosResponse. +type ListCombosResponse struct { + // Combos List of combo contracts matching the query + Combos []ComboResponse `json:"combos"` + Pagination Pagination `json:"pagination"` +} + +// MakerRebateLifetimeSummary defines model for MakerRebateLifetimeSummary. +type MakerRebateLifetimeSummary struct { + // FirstPayoutDate Date of the earliest payout in the window, or `null` if no payouts exist. + FirstPayoutDate *openapi_types.Date `json:"first_payout_date"` + + // LastPayoutDate Date of the most recent payout in the window, or `null` if no payouts exist. + LastPayoutDate *openapi_types.Date `json:"last_payout_date"` + + // PayoutCount Number of payouts in the window. Always present; `0` when no payouts exist in the window. + PayoutCount int32 `json:"payout_count"` + + // TotalEarnedUsd Sum of `total_rebate_usd` across payouts in the window. + TotalEarnedUsd string `json:"total_earned_usd"` + + // TotalFillCount Sum of qualifying maker fills across payouts in the window. + TotalFillCount int64 `json:"total_fill_count"` + + // TotalVolumeUsd Sum of qualifying maker volume (USD) across payouts in the window. + TotalVolumeUsd string `json:"total_volume_usd"` +} + +// MakerRebatePayout defines model for MakerRebatePayout. +type MakerRebatePayout struct { + // CreatedAt ISO-8601 timestamp at which the payout row was created. Always present. + CreatedAt *time.Time `json:"created_at"` + + // Id Stable payout identifier. + Id int64 `json:"id"` + + // PaidAt ISO-8601 timestamp at which the rebate was credited. Always present; `null` for payouts that have not yet been paid. + PaidAt *time.Time `json:"paid_at"` + + // Status Payout status (e.g. `PENDING`, `PAID`). + Status string `json:"status"` + + // TotalFillCount Number of qualifying maker fills that contributed to the payout. + TotalFillCount int32 `json:"total_fill_count"` + + // TotalRebateUsd Total rebate paid, in USD. + TotalRebateUsd string `json:"total_rebate_usd"` + + // TotalVolumeUsd Total qualifying maker volume contributing to this payout, in USD. + TotalVolumeUsd string `json:"total_volume_usd"` +} + +// MakerRebatePayoutsResponse defines model for MakerRebatePayoutsResponse. +type MakerRebatePayoutsResponse struct { + Payouts []MakerRebatePayout `json:"payouts"` +} + +// MakerRebateRateRule defines model for MakerRebateRateRule. +type MakerRebateRateRule struct { + // Category Market category this rule applies to. When absent, the rule applies to all categories. + Category *string `json:"category,omitempty"` + + // EffectiveFrom ISO-8601 timestamp at which this rule becomes effective. Always present; in practice never `null`. + EffectiveFrom *time.Time `json:"effective_from"` + + // EffectiveTo ISO-8601 timestamp after which this rule is superseded. Omitted when the rule is still current. + EffectiveTo *time.Time `json:"effective_to,omitempty"` + + // Id Stable identifier for this rate rule. + Id int64 `json:"id"` + + // RebateMultiplierBps Portion of the maker fee that is rebated, in basis points (10000 bps = 100%). + RebateMultiplierBps int32 `json:"rebate_multiplier_bps"` +} + +// MakerRebateRatesResponse defines model for MakerRebateRatesResponse. +type MakerRebateRatesResponse struct { + RateRules []MakerRebateRateRule `json:"rate_rules"` +} + +// MarketStatus Status of a prediction market +type MarketStatus string + +// MarketType Type of prediction market +type MarketType string + +// OrderBook defines model for OrderBook. +type OrderBook struct { + Asks *[]OrderBookEntry `json:"asks,omitempty"` + Bids *[]OrderBookEntry `json:"bids,omitempty"` +} + +// OrderBookDepth defines model for OrderBookDepth. +type OrderBookDepth struct { + Asks *[]OrderBookLevel `json:"asks,omitempty"` + Bids *[]OrderBookLevel `json:"bids,omitempty"` + LastUpdateTime *time.Time `json:"lastUpdateTime,omitempty"` +} + +// OrderBookEntry defines model for OrderBookEntry. +type OrderBookEntry struct { + Price *string `json:"price,omitempty"` + Quantity *string `json:"quantity,omitempty"` + Side *OrderSide `json:"side,omitempty"` +} + +// OrderBookLevel defines model for OrderBookLevel. +type OrderBookLevel struct { + OrderCount *int `json:"orderCount,omitempty"` + Price *string `json:"price,omitempty"` + Quantity *string `json:"quantity,omitempty"` +} + +// OrderRequest defines model for OrderRequest. +type OrderRequest struct { + // MakerOrCancel Set to `true` to require maker-only behavior. If the order would immediately take liquidity, the order is cancelled instead of filling. + MakerOrCancel *bool `json:"makerOrCancel,omitempty"` + + // OrderType Order type. `stop-limit` orders require a `stopPrice` that triggers a limit order at `price` when the market reaches the trigger. + OrderType OrderType `json:"orderType"` + + // Outcome The outcome being traded (Yes or No) + Outcome Outcome `json:"outcome"` + + // Price Limit price (0-1 range) + Price string `json:"price"` + + // Quantity Number of contracts + Quantity string `json:"quantity"` + Side OrderSide `json:"side"` + + // StopPrice The price to trigger a stop-limit order (0-1 range). Only available for stop-limit orders. See [Stop-Limit Orders](#operation/placeOrder) above for `stopPrice`/`price` constraints. + StopPrice *string `json:"stopPrice,omitempty"` + + // Symbol Contract instrument symbol + Symbol string `json:"symbol"` + + // TimeInForce Order execution behavior: + // - `good-til-cancel` - Order remains active until filled or cancelled (default) + // - `immediate-or-cancel` - Fill immediately or cancel remaining + // - `fill-or-kill` - Fill entire order immediately or cancel + TimeInForce *TimeInForce `json:"timeInForce,omitempty"` +} + +// OrderResponse defines model for OrderResponse. +type OrderResponse struct { + // AvgExecutionPrice Average price of fills + AvgExecutionPrice *string `json:"avgExecutionPrice,omitempty"` + CancelledAt *time.Time `json:"cancelledAt,omitempty"` + ClientOrderId *string `json:"clientOrderId,omitempty"` + ContractMetadata *ContractMetadata `json:"contractMetadata,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + + // FilledQuantity Amount filled so far + FilledQuantity *string `json:"filledQuantity,omitempty"` + GlobalOrderId *string `json:"globalOrderId,omitempty"` + HashOrderId *string `json:"hashOrderId,omitempty"` + OrderId *int64 `json:"orderId,omitempty"` + + // OrderType Order type. `stop-limit` orders require a `stopPrice` that triggers a limit order at `price` when the market reaches the trigger. + OrderType *OrderType `json:"orderType,omitempty"` + + // Outcome The outcome being traded (Yes or No) + Outcome *Outcome `json:"outcome,omitempty"` + + // Price Limit price + Price *string `json:"price,omitempty"` + + // Quantity Original order quantity + Quantity *string `json:"quantity,omitempty"` + + // RemainingQuantity Amount remaining to fill + RemainingQuantity *string `json:"remainingQuantity,omitempty"` + Side *OrderSide `json:"side,omitempty"` + Status *OrderStatus `json:"status,omitempty"` + + // StopPrice Stop trigger price (populated for `stop-limit` orders) + StopPrice *string `json:"stopPrice,omitempty"` + Symbol *string `json:"symbol,omitempty"` + UpdatedAt *time.Time `json:"updatedAt,omitempty"` +} + +// OrderSide defines model for OrderSide. +type OrderSide string + +// OrderStatus defines model for OrderStatus. +type OrderStatus string + +// OrderType Order type. `stop-limit` orders require a `stopPrice` that triggers a limit order at `price` when the market reaches the trigger. +type OrderType string + +// OrdersResponse defines model for OrdersResponse. +type OrdersResponse struct { + Orders *[]OrderResponse `json:"orders,omitempty"` + Pagination *PaginationSimple `json:"pagination,omitempty"` +} + +// Outcome The outcome being traded (Yes or No) +type Outcome string + +// Pagination defines model for Pagination. +type Pagination struct { + Limit *int `json:"limit,omitempty"` + Offset *int `json:"offset,omitempty"` + Total *int `json:"total,omitempty"` +} + +// PaginationSimple defines model for PaginationSimple. +type PaginationSimple struct { + // Count Number of items in current response + Count *int `json:"count,omitempty"` + Limit *int `json:"limit,omitempty"` + Offset *int `json:"offset,omitempty"` +} + +// PlaceOrderBatchErrorResult defines model for PlaceOrderBatchErrorResult. +type PlaceOrderBatchErrorResult struct { + // Error Error class for a rejected entry + Error string `json:"error"` + + // Message Human-readable detail for a rejected entry + Message string `json:"message"` +} + +// PlaceOrderBatchRequest defines model for PlaceOrderBatchRequest. +type PlaceOrderBatchRequest struct { + // Orders Orders to submit. Every entry is validated before any order is submitted. All orders use the account associated with the authenticated request. + Orders []OrderRequest `json:"orders"` +} + +// PlaceOrderBatchResponse defines model for PlaceOrderBatchResponse. +type PlaceOrderBatchResponse struct { + // Results One result for each submitted order, in request order. + Results []PlaceOrderBatchResult `json:"results"` +} + +// PlaceOrderBatchResult Exactly one outcome is present. Accepted entries contain `order`; rejected entries contain `error` and `message`. +type PlaceOrderBatchResult struct { + union json.RawMessage +} + +// PlaceOrderBatchSuccessResult defines model for PlaceOrderBatchSuccessResult. +type PlaceOrderBatchSuccessResult struct { + // Order An accepted order returned for one batch entry. + Order BatchOrderResponse `json:"order"` +} + +// Position defines model for Position. +type Position struct { + // AvgPrice Average entry price + AvgPrice *string `json:"avgPrice,omitempty"` + ContractMetadata *ContractMetadata `json:"contractMetadata,omitempty"` + InstrumentId *int64 `json:"instrumentId,omitempty"` + + // IsAboveAutoStartThreshold Whether the position is above the auto-start threshold + IsAboveAutoStartThreshold *bool `json:"isAboveAutoStartThreshold,omitempty"` + + // IsLive Whether the market is currently live/active + IsLive *bool `json:"isLive,omitempty"` + + // MarketValue Mark-to-market value of the position in USD at the current sell price (bestBid for YES, bestAsk for NO). **Absent** from the response when the held outcome has no live sell quote (no liquidity to sell into) — surface a no-liquidity state rather than a price the user cannot transact at. `lastTradePrice` is still returned for display. Treat as `Optional`. + MarketValue *string `json:"marketValue,omitempty"` + + // Outcome The outcome being traded (Yes or No) + Outcome *Outcome `json:"outcome,omitempty"` + + // Prices Current bid/ask/last-trade prices for the contract + Prices *PositionPrices `json:"prices,omitempty"` + + // QuantityOnHold Quantity currently on hold from open orders + QuantityOnHold *string `json:"quantityOnHold,omitempty"` + + // RealizedPl Realized profit/loss from sells + RealizedPl *string `json:"realizedPl,omitempty"` + + // ResolutionSide Winning outcome ("yes" or "no") if the contract has resolved + ResolutionSide *string `json:"resolutionSide,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // TotalQuantity Total position size + TotalQuantity *string `json:"totalQuantity,omitempty"` + + // UnrealizedPct Unrealized P&L as a percentage of cost basis. Expressed as a percent (e.g. `12.5` represents 12.5%, **not** `0.125`); rounded to 4 decimal places. **Absent** when there is no live sell quote, or when cost basis is zero. Treat as `Optional`. + UnrealizedPct *float64 `json:"unrealizedPct,omitempty"` + + // UnrealizedPnl Unrealized P&L in USD (`marketValue - costBasis`). **Absent** whenever `marketValue` is absent. Treat as `Optional`. + UnrealizedPnl *string `json:"unrealizedPnl,omitempty"` +} + +// PositionPrices Current bid/ask/last-trade prices for the contract +type PositionPrices struct { + BestAsk *string `json:"bestAsk,omitempty"` + BestBid *string `json:"bestBid,omitempty"` + Buy struct { + No *string `json:"no,omitempty"` + Yes *string `json:"yes,omitempty"` + } `json:"buy"` + LastTradePrice *string `json:"lastTradePrice,omitempty"` + Sell struct { + No *string `json:"no,omitempty"` + Yes *string `json:"yes,omitempty"` + } `json:"sell"` +} + +// PositionStatus defines model for PositionStatus. +type PositionStatus string + +// PositionsResponse defines model for PositionsResponse. +type PositionsResponse struct { + Positions *[]Position `json:"positions,omitempty"` + + // Total Total number of positions (for pagination) + Total *int `json:"total,omitempty"` +} + +// PredictionMarketHourlyVolumeCategory defines model for PredictionMarketHourlyVolumeCategory. +type PredictionMarketHourlyVolumeCategory struct { + // CategoryPath Display-name path from the top-level category to this category. It replaces recursive child nodes. + CategoryPath []string `json:"categoryPath"` + + // PeriodStart Inclusive UTC start of this hourly period. + PeriodStart time.Time `json:"periodStart"` + + // Volume Total volume for this category in this hour, including all descendant categories. + Volume PredictionMarketVolumeDecimal `json:"volume"` +} + +// PredictionMarketVolumeCategory defines model for PredictionMarketVolumeCategory. +type PredictionMarketVolumeCategory struct { + // CategoryPath Display-name path from the top-level category to this category. It replaces recursive child nodes. + CategoryPath []string `json:"categoryPath"` + + // Volume Total volume for this category, including all descendant categories. + Volume PredictionMarketVolumeDecimal `json:"volume"` +} + +// PredictionMarketVolumeDecimal Non-negative decimal string. Preserve it as a string to avoid floating-point precision loss. +type PredictionMarketVolumeDecimal = string + +// PredictionMarketsError defines model for PredictionMarketsError. +type PredictionMarketsError struct { + // Error Prediction Markets error class + Error string `json:"error"` + + // Field Request field associated with the error, when available + Field *string `json:"field,omitempty"` + + // Message Human-readable error detail, when available + Message *string `json:"message,omitempty"` +} + +// PredictionMarketsTerms defines model for PredictionMarketsTerms. +type PredictionMarketsTerms struct { + // Content Terms content to display before acceptance + Content string `json:"content"` + + // TermsType Terms type identifier + TermsType string `json:"termsType"` + + // UpdatedAt UTC timestamp when the terms content was last updated + UpdatedAt time.Time `json:"updatedAt"` + + // Version Latest terms version + Version int `json:"version"` +} + +// PredictionMarketsTermsStatus defines model for PredictionMarketsTermsStatus. +type PredictionMarketsTermsStatus struct { + // AcceptedVersion Latest terms version accepted by the account group, if any + AcceptedVersion *int `json:"acceptedVersion,omitempty"` + + // HasAcceptedLatest Whether the account group has accepted the latest configured Prediction Markets terms + HasAcceptedLatest bool `json:"hasAcceptedLatest"` + + // LatestVersion Latest configured Prediction Markets terms version, if available + LatestVersion *int `json:"latestVersion,omitempty"` +} + +// PricePoint defines model for PricePoint. +type PricePoint struct { + Price *string `json:"price,omitempty"` + Timestamp *time.Time `json:"timestamp,omitempty"` +} + +// RestrictedSellOnlyError defines model for RestrictedSellOnlyError. +type RestrictedSellOnlyError struct { + Error RestrictedSellOnlyErrorError `json:"error"` + Message RestrictedSellOnlyErrorMessage `json:"message"` +} + +// RestrictedSellOnlyErrorError defines model for RestrictedSellOnlyError.Error. +type RestrictedSellOnlyErrorError string + +// RestrictedSellOnlyErrorMessage defines model for RestrictedSellOnlyError.Message. +type RestrictedSellOnlyErrorMessage string + +// SettledPosition A historically settled position in a resolved prediction market contract. +type SettledPosition struct { + // AccountId Account that held the position + AccountId *int64 `json:"accountId,omitempty"` + ContractMetadata *ContractMetadata `json:"contractMetadata,omitempty"` + + // CostBasis Total amount spent to enter the position, net of any prior realized P&L from partial sells. Omitted when cost-basis data is not available. + CostBasis *string `json:"costBasis,omitempty"` + + // InstrumentId Unique instrument identifier for the contract + InstrumentId *int64 `json:"instrumentId,omitempty"` + + // InstrumentSymbol Contract instrument symbol + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // NetProfit Net profit for the position, computed as `payout - costBasis + realizedPnl`. Omitted when `costBasis` is not available. + NetProfit *string `json:"netProfit,omitempty"` + + // Outcome The outcome being traded (Yes or No) + Outcome *Outcome `json:"outcome,omitempty"` + + // Payout Payout received from settlement. `0` when the position lost. + Payout *string `json:"payout,omitempty"` + + // Position Signed position held at settlement. Positive values represent a `yes` position; negative values represent a `no` position. + Position *string `json:"position,omitempty"` + + // PositionQuantity Absolute quantity held at settlement (unsigned) + PositionQuantity *string `json:"positionQuantity,omitempty"` + + // RealizedPnl Realized profit or loss recorded from sells prior to settlement. Omitted when not available. + RealizedPnl *string `json:"realizedPnl,omitempty"` + + // ResolutionSide The winning outcome of the contract + ResolutionSide *Outcome `json:"resolutionSide,omitempty"` + + // SettledAt Settlement timestamp (ISO 8601) + SettledAt *time.Time `json:"settledAt,omitempty"` +} + +// SettledPositionsResponse defines model for SettledPositionsResponse. +type SettledPositionsResponse struct { + // CashOuts Cash-outs (early sells before contract resolution) in the same account-scoped time window as the returned page's settled positions. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. `positions[]` pagination is unaffected — `limit`/`offset` continue to scope `positions[]` only. + CashOuts *[]CashedOutPosition `json:"cashOuts,omitempty"` + Positions *[]SettledPosition `json:"positions,omitempty"` + + // Total Total number of settled positions across all pages for the current filter set. + Total *int `json:"total,omitempty"` + + // TotalCashOutCostBasis Sum of `cashOuts[].costBasis` over the returned cash-outs. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. + TotalCashOutCostBasis *string `json:"totalCashOutCostBasis,omitempty"` + + // TotalCashOutNetProfit Sum of `cashOuts[].netProfit` over the returned cash-outs. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. + TotalCashOutNetProfit *string `json:"totalCashOutNetProfit,omitempty"` + + // TotalCashOutProceeds Sum of `cashOuts[].proceeds` over the returned cash-outs. Field is absent (not `null`) when `withCashOuts=true` is not passed on the request. + TotalCashOutProceeds *string `json:"totalCashOutProceeds,omitempty"` + + // TotalCostBasis Sum of `costBasis` across all settled positions in the filter set. Retained for binary back-compat; **field is absent (not `null`) on the unified backend** (see `totalPayout`). + TotalCostBasis *string `json:"totalCostBasis,omitempty"` + + // TotalNetProfit Sum of `netProfit` across all settled positions in the filter set. Retained for binary back-compat; **field is absent (not `null`) on the unified backend** (see `totalPayout`). + TotalNetProfit *string `json:"totalNetProfit,omitempty"` + + // TotalPayout Sum of `payout` across all settled positions in the filter set. Retained for binary back-compat with the legacy response shape; **field is absent (not `null`) on the unified backend** because computing a roll-up over the full filtered set would require a separate aggregate query (deferred until a partner asks). Play's default `OptionHandlers` omits absent `Option` fields rather than emitting `null`. + TotalPayout *string `json:"totalPayout,omitempty"` +} + +// Settlement Settlement information for resolved events +type Settlement struct { + // Value The observed settlement value (e.g., the price at expiry for crypto contracts) + Value *string `json:"value,omitempty"` +} + +// SourceDetails Structured data source information for price observation. Replaces the deprecated flat `source` string on the event and contract. Present for crypto Up/Down events. Both fields are omitted when not available. +type SourceDetails struct { + // Agency The data provider / vendor name. + Agency *string `json:"agency,omitempty"` + + // Index The specific data feed identifier (the value previously carried by the flat `source` field). + Index *string `json:"index,omitempty"` +} + +// SportsMarket Atomic sports-market classification shared by every contract grouped under the event. Present only for sports events. All fields except `metric` are required together. +type SportsMarket struct { + // Metric Statistic measured by the market. Interpret shared metric names using `sportsMarket.sport`. + Metric *SportsMarketMetric `json:"metric,omitempty"` + + // Scope Settlement scope. `ordinal` identifies one unit; `start` and `end` identify an inclusive range of units. + Scope SportsMarketScope `json:"scope"` + + // Sport Sport whose rules give the market's scope and metric their sport-specific meaning. + Sport SportsMarketSport `json:"sport"` + + // Subject What the market is about. `participant` covers non-player entrants such as drivers and horses. + Subject SportsMarketSubject `json:"subject"` + + // Type Conventional sports-market family. `subject`, `scope`, and `metric` provide detail within the family. This classification is independent of the event's structural `type` (`binary` or `categorical`). + Type SportsMarketType `json:"type"` +} + +// SportsMarketMetric Statistic measured by the market. Interpret shared metric names using `sportsMarket.sport`. +type SportsMarketMetric string + +// SportsMarketScope Settlement scope. `ordinal` identifies one unit; `start` and `end` identify an inclusive range of units. +type SportsMarketScope struct { + // End Optional inclusive end of a scope range, such as inning `5`. + End *int32 `json:"end,omitempty"` + + // Ordinal Optional ordinal within the scope type, such as half `1` or quarter `4`. + Ordinal *int32 `json:"ordinal,omitempty"` + + // Start Optional inclusive start of a scope range, such as inning `1`. + Start *int32 `json:"start,omitempty"` + + // Type Unit covered by the market. `full_contest` follows the market's official final-result rules; `regulation` covers scheduled regulation play only. Ordinal and range qualifiers are represented separately on `SportsMarketScope`. + Type SportsMarketScopeType `json:"type"` +} + +// SportsMarketScopeType Unit covered by the market. `full_contest` follows the market's official final-result rules; `regulation` covers scheduled regulation play only. Ordinal and range qualifiers are represented separately on `SportsMarketScope`. +type SportsMarketScopeType string + +// SportsMarketSport Sport whose rules give the market's scope and metric their sport-specific meaning. +type SportsMarketSport string + +// SportsMarketSubject What the market is about. `participant` covers non-player entrants such as drivers and horses. +type SportsMarketSubject string + +// SportsMarketType Conventional sports-market family. `subject`, `scope`, and `metric` provide detail within the family. This classification is independent of the event's structural `type` (`binary` or `categorical`). +type SportsMarketType string + +// Strike Strike price or contract threshold information for Up/Down crypto contracts and sports prediction market contracts. +type Strike struct { + // AvailableAt When the strike price becomes available + AvailableAt *time.Time `json:"availableAt,omitempty"` + + // Type Strike or condition inequality type for contract threshold evaluation. - `reference`: Crypto Up/Down reference strike price captured at `availableAt` time. - `above`: Higher/Lower contract threshold. - `spread`: Point, run, or goal handicap spread line. - `over`: Total or prop threshold evaluated as strict greater than (`>`). - `over_or_equal`: Total or prop threshold evaluated as greater than or equal to (`>=`). - `under`: Total or prop threshold evaluated as strict less than (`<`). - `under_or_equal`: Position, rank, or total threshold evaluated as less than or equal to (`<=`). + Type *StrikeType `json:"type,omitempty"` + + // Value The strike price value. Null for "reference" type strikes where the value is determined at availableAt time. For sports contracts, this represents the derived numeric strike value (e.g. spread margin, total line, or position/rank threshold). + Value *string `json:"value,omitempty"` +} + +// StrikeType Strike or condition inequality type for contract threshold evaluation. - `reference`: Crypto Up/Down reference strike price captured at `availableAt` time. - `above`: Higher/Lower contract threshold. - `spread`: Point, run, or goal handicap spread line. - `over`: Total or prop threshold evaluated as strict greater than (`>`). - `over_or_equal`: Total or prop threshold evaluated as greater than or equal to (`>=`). - `under`: Total or prop threshold evaluated as strict less than (`<`). - `under_or_equal`: Position, rank, or total threshold evaluated as less than or equal to (`<=`). +type StrikeType string + +// Subcategory Nested category information for the event +type Subcategory struct { + // Id Category identifier + Id *int `json:"id,omitempty"` + + // Name Display name + Name *string `json:"name,omitempty"` + + // Path Category hierarchy path + Path *[]string `json:"path,omitempty"` + + // Slug URL-friendly category identifier + Slug *string `json:"slug,omitempty"` +} + +// TermsNotAcceptedError defines model for TermsNotAcceptedError. +type TermsNotAcceptedError struct { + Error TermsNotAcceptedErrorError `json:"error"` + Message TermsNotAcceptedErrorMessage `json:"message"` +} + +// TermsNotAcceptedErrorError defines model for TermsNotAcceptedError.Error. +type TermsNotAcceptedErrorError string + +// TermsNotAcceptedErrorMessage defines model for TermsNotAcceptedError.Message. +type TermsNotAcceptedErrorMessage string + +// TimeInForce Order execution behavior: +// - `good-til-cancel` - Order remains active until filled or cancelled (default) +// - `immediate-or-cancel` - Fill immediately or cancel remaining +// - `fill-or-kill` - Fill entire order immediately or cancel +type TimeInForce string + +// VolumeMetricsResponse defines model for VolumeMetricsResponse. +type VolumeMetricsResponse struct { + Contracts *[]ContractShareVolume `json:"contracts,omitempty"` + + // EventTicker The event ticker + EventTicker *string `json:"eventTicker,omitempty"` +} + +// Limit defines model for Limit. +type Limit = int + +// Offset defines model for Offset. +type Offset = int + +// SportFilter defines model for SportFilter. +type SportFilter = []SportsMarketSport + +// SportsMarketMetricFilter defines model for SportsMarketMetricFilter. +type SportsMarketMetricFilter = []SportsMarketMetric + +// SportsMarketScopeFilter defines model for SportsMarketScopeFilter. +type SportsMarketScopeFilter = []SportsMarketScopeType + +// SportsMarketSubjectFilter defines model for SportsMarketSubjectFilter. +type SportsMarketSubjectFilter = []SportsMarketSubject + +// SportsMarketTypeFilter defines model for SportsMarketTypeFilter. +type SportsMarketTypeFilter = []SportsMarketType + +// BadRequest defines model for BadRequest. +type BadRequest = Error + +// InternalError defines model for InternalError. +type InternalError = Error + +// ServiceUnavailable defines model for ServiceUnavailable. +type ServiceUnavailable = Error + +// Unauthorized defines model for Unauthorized. +type Unauthorized = Error + +// apiKeyContextKey is the context key for apiKey security scheme +type apiKeyContextKey string + +// payloadAuthContextKey is the context key for payloadAuth security scheme +type payloadAuthContextKey string + +// signatureAuthContextKey is the context key for signatureAuth security scheme +type signatureAuthContextKey string + +// GetCategoriesParams defines parameters for GetCategories. +type GetCategoriesParams struct { + // Status Filter categories by event status + Status *[]MarketStatus `form:"status,omitempty" json:"status,omitempty"` +} + +// ListCombosParams defines parameters for ListCombos. +type ListCombosParams struct { + // Status Filter by combo contract status (for example, `Active`, `Settled`, or `Voided`). Defaults to `Active` when omitted. + Status *string `form:"status,omitempty" json:"status,omitempty"` + + // ContractId Filter to combos that contain a specific underlying contract ID as a leg + ContractId *int64 `form:"contractId,omitempty" json:"contractId,omitempty"` + + // InstrumentRegistered Filter by whether the combo has been registered with an instrument symbol + InstrumentRegistered *bool `form:"instrumentRegistered,omitempty" json:"instrumentRegistered,omitempty"` + + // Limit Maximum number of results to return (max 500) + Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of results to skip for pagination + Offset *Offset `form:"offset,omitempty" json:"offset,omitempty"` +} + +// ListEventsParams defines parameters for ListEvents. +type ListEventsParams struct { + // Status Filter by event status (can specify multiple) + Status *[]MarketStatus `form:"status,omitempty" json:"status,omitempty"` + + // Category Filter by category (can specify multiple). If omitted, returns events from all categories. + Category *[]string `form:"category,omitempty" json:"category,omitempty"` + + // Sport Filter by `sportsMarket.sport`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`; valid combinations with no matching events return an empty result. + Sport *SportFilter `form:"sport,omitempty" json:"sport,omitempty"` + + // SportsMarketType Filter by `sportsMarket.type`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketType *SportsMarketTypeFilter `form:"sports_market_type,omitempty" json:"sports_market_type,omitempty"` + + // SportsMarketSubject Filter by `sportsMarket.subject`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketSubject *SportsMarketSubjectFilter `form:"sports_market_subject,omitempty" json:"sports_market_subject,omitempty"` + + // SportsMarketScope Filter by `sportsMarket.scope.type`. Repeat the parameter to match any supplied value (OR). Ordinal and range qualifiers are not inferred by this filter. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketScope *SportsMarketScopeFilter `form:"sports_market_scope,omitempty" json:"sports_market_scope,omitempty"` + + // SportsMarketMetric Filter by `sportsMarket.metric`. Repeat the parameter to match any supplied value (OR). A metric can be queried without `sport`; use `sport` when its sport-specific meaning matters. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketMetric *SportsMarketMetricFilter `form:"sports_market_metric,omitempty" json:"sports_market_metric,omitempty"` + + // Search Search text to filter events by title + Search *string `form:"search,omitempty" json:"search,omitempty"` + + // Limit Maximum number of results to return (max 500) + Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of results to skip for pagination + Offset *Offset `form:"offset,omitempty" json:"offset,omitempty"` +} + +// ListNewlyListedEventsParams defines parameters for ListNewlyListedEvents. +type ListNewlyListedEventsParams struct { + // Category Filter by category (can specify multiple). If omitted, returns events from all categories. + Category *[]string `form:"category,omitempty" json:"category,omitempty"` + + // Sport Filter by `sportsMarket.sport`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`; valid combinations with no matching events return an empty result. + Sport *SportFilter `form:"sport,omitempty" json:"sport,omitempty"` + + // SportsMarketType Filter by `sportsMarket.type`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketType *SportsMarketTypeFilter `form:"sports_market_type,omitempty" json:"sports_market_type,omitempty"` + + // SportsMarketSubject Filter by `sportsMarket.subject`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketSubject *SportsMarketSubjectFilter `form:"sports_market_subject,omitempty" json:"sports_market_subject,omitempty"` + + // SportsMarketScope Filter by `sportsMarket.scope.type`. Repeat the parameter to match any supplied value (OR). Ordinal and range qualifiers are not inferred by this filter. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketScope *SportsMarketScopeFilter `form:"sports_market_scope,omitempty" json:"sports_market_scope,omitempty"` + + // SportsMarketMetric Filter by `sportsMarket.metric`. Repeat the parameter to match any supplied value (OR). A metric can be queried without `sport`; use `sport` when its sport-specific meaning matters. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketMetric *SportsMarketMetricFilter `form:"sports_market_metric,omitempty" json:"sports_market_metric,omitempty"` + + // Limit Maximum number of results to return (max 500) + Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of results to skip for pagination + Offset *Offset `form:"offset,omitempty" json:"offset,omitempty"` +} + +// ListRecentlySettledEventsParams defines parameters for ListRecentlySettledEvents. +type ListRecentlySettledEventsParams struct { + // Category Filter by category (can specify multiple). If omitted, returns events from all categories. + Category *[]string `form:"category,omitempty" json:"category,omitempty"` + + // Sport Filter by `sportsMarket.sport`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`; valid combinations with no matching events return an empty result. + Sport *SportFilter `form:"sport,omitempty" json:"sport,omitempty"` + + // SportsMarketType Filter by `sportsMarket.type`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketType *SportsMarketTypeFilter `form:"sports_market_type,omitempty" json:"sports_market_type,omitempty"` + + // SportsMarketSubject Filter by `sportsMarket.subject`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketSubject *SportsMarketSubjectFilter `form:"sports_market_subject,omitempty" json:"sports_market_subject,omitempty"` + + // SportsMarketScope Filter by `sportsMarket.scope.type`. Repeat the parameter to match any supplied value (OR). Ordinal and range qualifiers are not inferred by this filter. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketScope *SportsMarketScopeFilter `form:"sports_market_scope,omitempty" json:"sports_market_scope,omitempty"` + + // SportsMarketMetric Filter by `sportsMarket.metric`. Repeat the parameter to match any supplied value (OR). A metric can be queried without `sport`; use `sport` when its sport-specific meaning matters. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketMetric *SportsMarketMetricFilter `form:"sports_market_metric,omitempty" json:"sports_market_metric,omitempty"` + + // Limit Maximum number of results to return (max 500) + Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of results to skip for pagination + Offset *Offset `form:"offset,omitempty" json:"offset,omitempty"` +} + +// ListUpcomingEventsParams defines parameters for ListUpcomingEvents. +type ListUpcomingEventsParams struct { + // Category Filter by category (can specify multiple). If omitted, returns events from all categories. + Category *[]string `form:"category,omitempty" json:"category,omitempty"` + + // Sport Filter by `sportsMarket.sport`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`; valid combinations with no matching events return an empty result. + Sport *SportFilter `form:"sport,omitempty" json:"sport,omitempty"` + + // SportsMarketType Filter by `sportsMarket.type`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketType *SportsMarketTypeFilter `form:"sports_market_type,omitempty" json:"sports_market_type,omitempty"` + + // SportsMarketSubject Filter by `sportsMarket.subject`. Repeat the parameter to match any supplied value (OR). Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketSubject *SportsMarketSubjectFilter `form:"sports_market_subject,omitempty" json:"sports_market_subject,omitempty"` + + // SportsMarketScope Filter by `sportsMarket.scope.type`. Repeat the parameter to match any supplied value (OR). Ordinal and range qualifiers are not inferred by this filter. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketScope *SportsMarketScopeFilter `form:"sports_market_scope,omitempty" json:"sports_market_scope,omitempty"` + + // SportsMarketMetric Filter by `sportsMarket.metric`. Repeat the parameter to match any supplied value (OR). A metric can be queried without `sport`; use `sport` when its sport-specific meaning matters. Sports-market filters compose independently using AND. Unsupported enum values return `400 Bad Request`. + SportsMarketMetric *SportsMarketMetricFilter `form:"sports_market_metric,omitempty" json:"sports_market_metric,omitempty"` + + // Limit Maximum number of results to return (max 500) + Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of results to skip for pagination + Offset *Offset `form:"offset,omitempty" json:"offset,omitempty"` +} + +// ListLiquidityRewardsEventsParams defines parameters for ListLiquidityRewardsEvents. +type ListLiquidityRewardsEventsParams struct { + // Category Comma-separated list of category names. Whitespace is trimmed and empty entries are dropped. + Category *string `form:"category,omitempty" json:"category,omitempty"` + + // Search Filter events by title substring (case-insensitive). + Search *string `form:"search,omitempty" json:"search,omitempty"` + + // Sort Sort order for the returned events. Defaults to `daily_pool_desc`. + Sort *ListLiquidityRewardsEventsParamsSort `form:"sort,omitempty" json:"sort,omitempty"` + + // Limit Maximum number of events to return (default 50, clamped to [1, 100]). + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of events to skip (default 0). + Offset *int `form:"offset,omitempty" json:"offset,omitempty"` +} + +// ListLiquidityRewardsEventsParamsSort defines parameters for ListLiquidityRewardsEvents. +type ListLiquidityRewardsEventsParamsSort string + +// GetLiquidityRewardsDailySummaryParams defines parameters for GetLiquidityRewardsDailySummary. +type GetLiquidityRewardsDailySummaryParams struct { + // DateFrom Inclusive start of the date window (`YYYY-MM-DD`, Eastern Time). + DateFrom openapi_types.Date `form:"dateFrom" json:"dateFrom"` + + // DateTo Inclusive end of the date window (`YYYY-MM-DD`, Eastern Time). Must be on or after `dateFrom`. + DateTo openapi_types.Date `form:"dateTo" json:"dateTo"` +} + +// GetLiquidityRewardsLifetimeSummaryParams defines parameters for GetLiquidityRewardsLifetimeSummary. +type GetLiquidityRewardsLifetimeSummaryParams struct { + // DateFrom Inclusive start of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be provided together with `dateTo`. + DateFrom *openapi_types.Date `form:"dateFrom,omitempty" json:"dateFrom,omitempty"` + + // DateTo Inclusive end of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be on or after `dateFrom` and within 5 years of it. + DateTo *openapi_types.Date `form:"dateTo,omitempty" json:"dateTo,omitempty"` +} + +// ListMakerRebatePayoutsParams defines parameters for ListMakerRebatePayouts. +type ListMakerRebatePayoutsParams struct { + // Limit Maximum number of payouts to return (default 50, clamped to [1, 100]). + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of payouts to skip (default 0). + Offset *int `form:"offset,omitempty" json:"offset,omitempty"` +} + +// GetMakerRebateRatesParams defines parameters for GetMakerRebateRates. +type GetMakerRebateRatesParams struct { + // Category Filter to rules that apply to this category (e.g. `Crypto`, `Sports`). When omitted, returns all rules. + Category *string `form:"category,omitempty" json:"category,omitempty"` +} + +// GetMakerRebateLifetimeSummaryParams defines parameters for GetMakerRebateLifetimeSummary. +type GetMakerRebateLifetimeSummaryParams struct { + // DateFrom Inclusive start of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be provided together with `dateTo`. + DateFrom *openapi_types.Date `form:"dateFrom,omitempty" json:"dateFrom,omitempty"` + + // DateTo Inclusive end of the payout date window (`YYYY-MM-DD`, Eastern Time). Must be on or after `dateFrom` and within 5 years of it. + DateTo *openapi_types.Date `form:"dateTo,omitempty" json:"dateTo,omitempty"` +} + +// GetVolumeMetricsJSONBody defines parameters for GetVolumeMetrics. +type GetVolumeMetricsJSONBody struct { + // EndTime End of time range filter (epoch milliseconds). If omitted, includes all trades up to now. + EndTime *int64 `json:"endTime,omitempty"` + + // EventTicker The event ticker symbol + EventTicker string `json:"eventTicker"` + + // StartTime Start of time range filter (epoch milliseconds). If omitted, defaults to the earliest contract creation time. + StartTime *int64 `json:"startTime,omitempty"` +} + +// PlaceOrderBatch400JSONResponseBody defines parameters for PlaceOrderBatch. +type PlaceOrderBatch400JSONResponseBody struct { + union json.RawMessage +} + +// PlaceOrderBatch403JSONResponseBody defines parameters for PlaceOrderBatch. +type PlaceOrderBatch403JSONResponseBody struct { + union json.RawMessage +} + +// CancelOrderBatch400JSONResponseBody defines parameters for CancelOrderBatch. +type CancelOrderBatch400JSONResponseBody struct { + union json.RawMessage +} + +// CancelOrderJSONBody defines parameters for CancelOrder. +type CancelOrderJSONBody struct { + // OrderId The order ID to cancel + OrderId int64 `json:"orderId"` +} + +// GetActiveOrdersJSONBody defines parameters for GetActiveOrders. +type GetActiveOrdersJSONBody struct { + // Limit Maximum number of results to return (default 50, max 100) + Limit *int `json:"limit,omitempty"` + + // Offset Number of results to skip for pagination + Offset *int `json:"offset,omitempty"` + + // Symbol Filter by contract instrument symbol + Symbol *string `json:"symbol,omitempty"` +} + +// GetOrderHistoryJSONBody defines parameters for GetOrderHistory. +type GetOrderHistoryJSONBody struct { + // From Inclusive start of the order-closed time range, expressed as Unix epoch milliseconds. Use with `to` for a UTC daily window. + From *int64 `json:"from,omitempty"` + + // Limit Maximum number of results to return. Defaults to 50 and is capped at 1000. + Limit *int `json:"limit,omitempty"` + + // Offset Number of results to skip for pagination. Offset is ignored when `from` or `to` is supplied. + Offset *int `json:"offset,omitempty"` + + // Status Filter by order status + Status *GetOrderHistoryJSONBodyStatus `json:"status,omitempty"` + + // Symbol Filter by contract instrument symbol + Symbol *string `json:"symbol,omitempty"` + + // To Exclusive end of the order-closed time range, expressed as Unix epoch milliseconds. `from` must not be later than `to`. + To *int64 `json:"to,omitempty"` +} + +// GetOrderHistoryJSONBodyStatus defines parameters for GetOrderHistory. +type GetOrderHistoryJSONBodyStatus string + +// GetPositionsParams defines parameters for GetPositions. +type GetPositionsParams struct { + // EventTicker Filter positions to a single event ticker (e.g. `FEDJAN26`). Positions on sub-events whose `parentEventTicker` matches the value may also be included. + EventTicker *string `form:"eventTicker,omitempty" json:"eventTicker,omitempty"` + + // Limit Maximum number of positions to return. Clamped to `[1, 1000]` when supplied. Omit for legacy unpaginated behavior. + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of positions to skip for pagination. Floor-clamped to `0` when supplied. Ignored when `limit` is omitted (the response is unpaginated). + Offset *int `form:"offset,omitempty" json:"offset,omitempty"` + + // Sort Sort order. Accepts `positionValue`, `unrealizedPnl`, or `expiryDate` (case-insensitive), optionally prefixed with `+` (ascending) or `-` (descending). A bare field name uses each field's default direction: `positionValue` and `unrealizedPnl` default to descending; `expiryDate` defaults to ascending (soonest-first). `unrealizedPnl` and `expiryDate` sort NULLS LAST so positions without the sort key sink to the bottom regardless of direction. `instrumentId` ascending is the final tiebreaker for stable pagination across quote ticks. A malformed `sort` value silently falls back to `-positionValue` — no `400` is returned. + Sort *GetPositionsParamsSort `form:"sort,omitempty" json:"sort,omitempty"` +} + +// GetPositionsParamsSort defines parameters for GetPositions. +type GetPositionsParamsSort string + +// GetSettledPositionsParams defines parameters for GetSettledPositions. +type GetSettledPositionsParams struct { + // EventTicker Optional event ticker to filter settled positions to a single event (e.g. `FEDJAN26`). If omitted, all settled positions for the account are returned. + EventTicker *string `form:"eventTicker,omitempty" json:"eventTicker,omitempty"` + + // Limit Maximum number of settled positions to return. + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Number of settled positions to skip for pagination. + Offset *int `form:"offset,omitempty" json:"offset,omitempty"` + + // Sort Sort order. Accepts `date` or `payout`, optionally prefixed with `+` (ascending) or `-` (descending). A bare field name defaults to descending. `date` ascending is rejected and silently falls back to the default order — settled positions are conceptually ordered most-recent-first. A malformed `sort` value also falls back silently; no `400` is returned. + Sort *GetSettledPositionsParamsSort `form:"sort,omitempty" json:"sort,omitempty"` + + // Search Case-insensitive substring filter. Matches against the event name, contract name, event ticker, or any ancestor category name in the contract's category subtree (up to four levels). Whitespace is trimmed; inputs under 3 characters are dropped (GIN trigram lookup floor); inputs over 64 characters are truncated. + Search *string `form:"search,omitempty" json:"search,omitempty"` + + // Category Filter to settled positions whose contract's event belongs to the named category (or any of its descendants in the category tree). Whitespace is trimmed; empty values are ignored. + Category *string `form:"category,omitempty" json:"category,omitempty"` + + // WithCashOuts Opt-in flag. When `true`, the response carries new sibling fields (`cashOuts`, `totalCashOutProceeds`, `totalCashOutCostBasis`, `totalCashOutNetProfit`) populated with the qualifying cash-outs in the same account-scoped time window as the returned page's settled positions. When `false` (default) the response shape is byte-identical to the pre-`withCashOuts` contract: the `positions[]` element schema is unchanged regardless of the flag. + WithCashOuts *bool `form:"withCashOuts,omitempty" json:"withCashOuts,omitempty"` +} + +// GetSettledPositionsParamsSort defines parameters for GetSettledPositions. +type GetSettledPositionsParamsSort string + +// CreateComboJSONRequestBody defines body for CreateCombo for application/json ContentType. +type CreateComboJSONRequestBody = CreateComboRequest + +// GetVolumeMetricsJSONRequestBody defines body for GetVolumeMetrics for application/json ContentType. +type GetVolumeMetricsJSONRequestBody GetVolumeMetricsJSONBody + +// PlaceOrderJSONRequestBody defines body for PlaceOrder for application/json ContentType. +type PlaceOrderJSONRequestBody = OrderRequest + +// PlaceOrderBatchJSONRequestBody defines body for PlaceOrderBatch for application/json ContentType. +type PlaceOrderBatchJSONRequestBody = PlaceOrderBatchRequest + +// CancelOrderBatchJSONRequestBody defines body for CancelOrderBatch for application/json ContentType. +type CancelOrderBatchJSONRequestBody = CancelOrderBatchRequest + +// CancelOrderJSONRequestBody defines body for CancelOrder for application/json ContentType. +type CancelOrderJSONRequestBody CancelOrderJSONBody + +// GetActiveOrdersJSONRequestBody defines body for GetActiveOrders for application/json ContentType. +type GetActiveOrdersJSONRequestBody GetActiveOrdersJSONBody + +// GetOrderHistoryJSONRequestBody defines body for GetOrderHistory for application/json ContentType. +type GetOrderHistoryJSONRequestBody GetOrderHistoryJSONBody + +// AsCancelOrderBatchRequestOrderIds0 returns the union data inside the CancelOrderBatchRequest_OrderIds_Item as a CancelOrderBatchRequestOrderIds0 +func (t CancelOrderBatchRequest_OrderIds_Item) AsCancelOrderBatchRequestOrderIds0() (CancelOrderBatchRequestOrderIds0, error) { + var body CancelOrderBatchRequestOrderIds0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromCancelOrderBatchRequestOrderIds0 overwrites any union data inside the CancelOrderBatchRequest_OrderIds_Item as the provided CancelOrderBatchRequestOrderIds0 +func (t *CancelOrderBatchRequest_OrderIds_Item) FromCancelOrderBatchRequestOrderIds0(v CancelOrderBatchRequestOrderIds0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeCancelOrderBatchRequestOrderIds0 performs a merge with any union data inside the CancelOrderBatchRequest_OrderIds_Item, using the provided CancelOrderBatchRequestOrderIds0 +func (t *CancelOrderBatchRequest_OrderIds_Item) MergeCancelOrderBatchRequestOrderIds0(v CancelOrderBatchRequestOrderIds0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsCancelOrderBatchRequestOrderIds1 returns the union data inside the CancelOrderBatchRequest_OrderIds_Item as a CancelOrderBatchRequestOrderIds1 +func (t CancelOrderBatchRequest_OrderIds_Item) AsCancelOrderBatchRequestOrderIds1() (CancelOrderBatchRequestOrderIds1, error) { + var body CancelOrderBatchRequestOrderIds1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromCancelOrderBatchRequestOrderIds1 overwrites any union data inside the CancelOrderBatchRequest_OrderIds_Item as the provided CancelOrderBatchRequestOrderIds1 +func (t *CancelOrderBatchRequest_OrderIds_Item) FromCancelOrderBatchRequestOrderIds1(v CancelOrderBatchRequestOrderIds1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeCancelOrderBatchRequestOrderIds1 performs a merge with any union data inside the CancelOrderBatchRequest_OrderIds_Item, using the provided CancelOrderBatchRequestOrderIds1 +func (t *CancelOrderBatchRequest_OrderIds_Item) MergeCancelOrderBatchRequestOrderIds1(v CancelOrderBatchRequestOrderIds1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t CancelOrderBatchRequest_OrderIds_Item) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *CancelOrderBatchRequest_OrderIds_Item) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsCancelOrderBatchSuccessResult returns the union data inside the CancelOrderBatchResult as a CancelOrderBatchSuccessResult +func (t CancelOrderBatchResult) AsCancelOrderBatchSuccessResult() (CancelOrderBatchSuccessResult, error) { + var body CancelOrderBatchSuccessResult + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromCancelOrderBatchSuccessResult overwrites any union data inside the CancelOrderBatchResult as the provided CancelOrderBatchSuccessResult +func (t *CancelOrderBatchResult) FromCancelOrderBatchSuccessResult(v CancelOrderBatchSuccessResult) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeCancelOrderBatchSuccessResult performs a merge with any union data inside the CancelOrderBatchResult, using the provided CancelOrderBatchSuccessResult +func (t *CancelOrderBatchResult) MergeCancelOrderBatchSuccessResult(v CancelOrderBatchSuccessResult) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsCancelOrderBatchErrorResult returns the union data inside the CancelOrderBatchResult as a CancelOrderBatchErrorResult +func (t CancelOrderBatchResult) AsCancelOrderBatchErrorResult() (CancelOrderBatchErrorResult, error) { + var body CancelOrderBatchErrorResult + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromCancelOrderBatchErrorResult overwrites any union data inside the CancelOrderBatchResult as the provided CancelOrderBatchErrorResult +func (t *CancelOrderBatchResult) FromCancelOrderBatchErrorResult(v CancelOrderBatchErrorResult) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeCancelOrderBatchErrorResult performs a merge with any union data inside the CancelOrderBatchResult, using the provided CancelOrderBatchErrorResult +func (t *CancelOrderBatchResult) MergeCancelOrderBatchErrorResult(v CancelOrderBatchErrorResult) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t CancelOrderBatchResult) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *CancelOrderBatchResult) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsPlaceOrderBatchSuccessResult returns the union data inside the PlaceOrderBatchResult as a PlaceOrderBatchSuccessResult +func (t PlaceOrderBatchResult) AsPlaceOrderBatchSuccessResult() (PlaceOrderBatchSuccessResult, error) { + var body PlaceOrderBatchSuccessResult + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPlaceOrderBatchSuccessResult overwrites any union data inside the PlaceOrderBatchResult as the provided PlaceOrderBatchSuccessResult +func (t *PlaceOrderBatchResult) FromPlaceOrderBatchSuccessResult(v PlaceOrderBatchSuccessResult) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePlaceOrderBatchSuccessResult performs a merge with any union data inside the PlaceOrderBatchResult, using the provided PlaceOrderBatchSuccessResult +func (t *PlaceOrderBatchResult) MergePlaceOrderBatchSuccessResult(v PlaceOrderBatchSuccessResult) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPlaceOrderBatchErrorResult returns the union data inside the PlaceOrderBatchResult as a PlaceOrderBatchErrorResult +func (t PlaceOrderBatchResult) AsPlaceOrderBatchErrorResult() (PlaceOrderBatchErrorResult, error) { + var body PlaceOrderBatchErrorResult + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPlaceOrderBatchErrorResult overwrites any union data inside the PlaceOrderBatchResult as the provided PlaceOrderBatchErrorResult +func (t *PlaceOrderBatchResult) FromPlaceOrderBatchErrorResult(v PlaceOrderBatchErrorResult) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePlaceOrderBatchErrorResult performs a merge with any union data inside the PlaceOrderBatchResult, using the provided PlaceOrderBatchErrorResult +func (t *PlaceOrderBatchResult) MergePlaceOrderBatchErrorResult(v PlaceOrderBatchErrorResult) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PlaceOrderBatchResult) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PlaceOrderBatchResult) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsAuthErrorResponse returns the union data inside the PlaceOrderBatch400JSONResponseBody as a AuthErrorResponse +func (t PlaceOrderBatch400JSONResponseBody) AsAuthErrorResponse() (AuthErrorResponse, error) { + var body AuthErrorResponse + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAuthErrorResponse overwrites any union data inside the PlaceOrderBatch400JSONResponseBody as the provided AuthErrorResponse +func (t *PlaceOrderBatch400JSONResponseBody) FromAuthErrorResponse(v AuthErrorResponse) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAuthErrorResponse performs a merge with any union data inside the PlaceOrderBatch400JSONResponseBody, using the provided AuthErrorResponse +func (t *PlaceOrderBatch400JSONResponseBody) MergeAuthErrorResponse(v AuthErrorResponse) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPredictionMarketsError returns the union data inside the PlaceOrderBatch400JSONResponseBody as a PredictionMarketsError +func (t PlaceOrderBatch400JSONResponseBody) AsPredictionMarketsError() (PredictionMarketsError, error) { + var body PredictionMarketsError + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPredictionMarketsError overwrites any union data inside the PlaceOrderBatch400JSONResponseBody as the provided PredictionMarketsError +func (t *PlaceOrderBatch400JSONResponseBody) FromPredictionMarketsError(v PredictionMarketsError) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePredictionMarketsError performs a merge with any union data inside the PlaceOrderBatch400JSONResponseBody, using the provided PredictionMarketsError +func (t *PlaceOrderBatch400JSONResponseBody) MergePredictionMarketsError(v PredictionMarketsError) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PlaceOrderBatch400JSONResponseBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PlaceOrderBatch400JSONResponseBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsAuthErrorResponse returns the union data inside the PlaceOrderBatch403JSONResponseBody as a AuthErrorResponse +func (t PlaceOrderBatch403JSONResponseBody) AsAuthErrorResponse() (AuthErrorResponse, error) { + var body AuthErrorResponse + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAuthErrorResponse overwrites any union data inside the PlaceOrderBatch403JSONResponseBody as the provided AuthErrorResponse +func (t *PlaceOrderBatch403JSONResponseBody) FromAuthErrorResponse(v AuthErrorResponse) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAuthErrorResponse performs a merge with any union data inside the PlaceOrderBatch403JSONResponseBody, using the provided AuthErrorResponse +func (t *PlaceOrderBatch403JSONResponseBody) MergeAuthErrorResponse(v AuthErrorResponse) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsAccountGroupBlockedError returns the union data inside the PlaceOrderBatch403JSONResponseBody as a AccountGroupBlockedError +func (t PlaceOrderBatch403JSONResponseBody) AsAccountGroupBlockedError() (AccountGroupBlockedError, error) { + var body AccountGroupBlockedError + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAccountGroupBlockedError overwrites any union data inside the PlaceOrderBatch403JSONResponseBody as the provided AccountGroupBlockedError +func (t *PlaceOrderBatch403JSONResponseBody) FromAccountGroupBlockedError(v AccountGroupBlockedError) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAccountGroupBlockedError performs a merge with any union data inside the PlaceOrderBatch403JSONResponseBody, using the provided AccountGroupBlockedError +func (t *PlaceOrderBatch403JSONResponseBody) MergeAccountGroupBlockedError(v AccountGroupBlockedError) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTermsNotAcceptedError returns the union data inside the PlaceOrderBatch403JSONResponseBody as a TermsNotAcceptedError +func (t PlaceOrderBatch403JSONResponseBody) AsTermsNotAcceptedError() (TermsNotAcceptedError, error) { + var body TermsNotAcceptedError + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTermsNotAcceptedError overwrites any union data inside the PlaceOrderBatch403JSONResponseBody as the provided TermsNotAcceptedError +func (t *PlaceOrderBatch403JSONResponseBody) FromTermsNotAcceptedError(v TermsNotAcceptedError) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTermsNotAcceptedError performs a merge with any union data inside the PlaceOrderBatch403JSONResponseBody, using the provided TermsNotAcceptedError +func (t *PlaceOrderBatch403JSONResponseBody) MergeTermsNotAcceptedError(v TermsNotAcceptedError) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsRestrictedSellOnlyError returns the union data inside the PlaceOrderBatch403JSONResponseBody as a RestrictedSellOnlyError +func (t PlaceOrderBatch403JSONResponseBody) AsRestrictedSellOnlyError() (RestrictedSellOnlyError, error) { + var body RestrictedSellOnlyError + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromRestrictedSellOnlyError overwrites any union data inside the PlaceOrderBatch403JSONResponseBody as the provided RestrictedSellOnlyError +func (t *PlaceOrderBatch403JSONResponseBody) FromRestrictedSellOnlyError(v RestrictedSellOnlyError) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeRestrictedSellOnlyError performs a merge with any union data inside the PlaceOrderBatch403JSONResponseBody, using the provided RestrictedSellOnlyError +func (t *PlaceOrderBatch403JSONResponseBody) MergeRestrictedSellOnlyError(v RestrictedSellOnlyError) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PlaceOrderBatch403JSONResponseBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PlaceOrderBatch403JSONResponseBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsAuthErrorResponse returns the union data inside the CancelOrderBatch400JSONResponseBody as a AuthErrorResponse +func (t CancelOrderBatch400JSONResponseBody) AsAuthErrorResponse() (AuthErrorResponse, error) { + var body AuthErrorResponse + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAuthErrorResponse overwrites any union data inside the CancelOrderBatch400JSONResponseBody as the provided AuthErrorResponse +func (t *CancelOrderBatch400JSONResponseBody) FromAuthErrorResponse(v AuthErrorResponse) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAuthErrorResponse performs a merge with any union data inside the CancelOrderBatch400JSONResponseBody, using the provided AuthErrorResponse +func (t *CancelOrderBatch400JSONResponseBody) MergeAuthErrorResponse(v AuthErrorResponse) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPredictionMarketsError returns the union data inside the CancelOrderBatch400JSONResponseBody as a PredictionMarketsError +func (t CancelOrderBatch400JSONResponseBody) AsPredictionMarketsError() (PredictionMarketsError, error) { + var body PredictionMarketsError + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPredictionMarketsError overwrites any union data inside the CancelOrderBatch400JSONResponseBody as the provided PredictionMarketsError +func (t *CancelOrderBatch400JSONResponseBody) FromPredictionMarketsError(v PredictionMarketsError) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePredictionMarketsError performs a merge with any union data inside the CancelOrderBatch400JSONResponseBody, using the provided PredictionMarketsError +func (t *CancelOrderBatch400JSONResponseBody) MergePredictionMarketsError(v PredictionMarketsError) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t CancelOrderBatch400JSONResponseBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *CancelOrderBatch400JSONResponseBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/packages/sdk-go/generated/trading/types.gen.go b/packages/sdk-go/generated/trading/types.gen.go new file mode 100644 index 0000000..7b1c4eb --- /dev/null +++ b/packages/sdk-go/generated/trading/types.gen.go @@ -0,0 +1,3064 @@ +// Code generated from rest.yaml (Orders, Session). DO NOT EDIT. + +// Package trading provides primitives to interact with the openapi HTTP API. +// +// Code generated by oapi-codegen. DO NOT EDIT. +package trading + +import ( + "encoding/json" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/internal/runtime" + openapi_types "github.com/gemini/developer-platform/packages/sdk-go/types" +) + +const ( + ApiKeyAuthScopes apiKeyAuthContextKey = "apiKeyAuth.Scopes" + PayloadAuthScopes payloadAuthContextKey = "payloadAuth.Scopes" + SignatureAuthScopes signatureAuthContextKey = "signatureAuth.Scopes" +) + +// Defines values for BalanceType. +const ( + Exchange BalanceType = "exchange" +) + +// Valid indicates whether the value is a known member of the BalanceType enum. +func (e BalanceType) Valid() bool { + switch e { + case Exchange: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseReason. +const ( + ExceedsPriceLimits CancelOrderResponseReason = "ExceedsPriceLimits" + FillOrKillWouldNotFill CancelOrderResponseReason = "FillOrKillWouldNotFill" + ImmediateOrCancelWouldPost CancelOrderResponseReason = "ImmediateOrCancelWouldPost" + MakerOrCancelWouldTake CancelOrderResponseReason = "MakerOrCancelWouldTake" + MarketClosed CancelOrderResponseReason = "MarketClosed" + Requested CancelOrderResponseReason = "Requested" + SelfCrossPrevented CancelOrderResponseReason = "SelfCrossPrevented" + TradingClosed CancelOrderResponseReason = "TradingClosed" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseReason enum. +func (e CancelOrderResponseReason) Valid() bool { + switch e { + case ExceedsPriceLimits: + return true + case FillOrKillWouldNotFill: + return true + case ImmediateOrCancelWouldPost: + return true + case MakerOrCancelWouldTake: + return true + case MarketClosed: + return true + case Requested: + return true + case SelfCrossPrevented: + return true + case TradingClosed: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseSide. +const ( + CancelOrderResponseSideBuy CancelOrderResponseSide = "buy" + CancelOrderResponseSideSell CancelOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseSide enum. +func (e CancelOrderResponseSide) Valid() bool { + switch e { + case CancelOrderResponseSideBuy: + return true + case CancelOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for CancelOrderResponseType. +const ( + CancelOrderResponseTypeExchangeLimit CancelOrderResponseType = "exchange limit" + CancelOrderResponseTypeExchangeMarket CancelOrderResponseType = "exchange market" + CancelOrderResponseTypeExchangeStopLimit CancelOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the CancelOrderResponseType enum. +func (e CancelOrderResponseType) Valid() bool { + switch e { + case CancelOrderResponseTypeExchangeLimit: + return true + case CancelOrderResponseTypeExchangeMarket: + return true + case CancelOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for ClearingOrderSide. +const ( + ClearingOrderSideBuy ClearingOrderSide = "buy" + ClearingOrderSideSell ClearingOrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the ClearingOrderSide enum. +func (e ClearingOrderSide) Valid() bool { + switch e { + case ClearingOrderSideBuy: + return true + case ClearingOrderSideSell: + return true + default: + return false + } +} + +// Defines values for FundingPaymentEventType. +const ( + FundingPaymentEventTypeHourlyFundingTransfer FundingPaymentEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentEventType enum. +func (e FundingPaymentEventType) Valid() bool { + switch e { + case FundingPaymentEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemAction. +const ( + FundingPaymentReportItemActionCredit FundingPaymentReportItemAction = "Credit" + FundingPaymentReportItemActionDebit FundingPaymentReportItemAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemAction enum. +func (e FundingPaymentReportItemAction) Valid() bool { + switch e { + case FundingPaymentReportItemActionCredit: + return true + case FundingPaymentReportItemActionDebit: + return true + default: + return false + } +} + +// Defines values for FundingPaymentReportItemEventType. +const ( + FundingPaymentReportItemEventTypeHourlyFundingTransfer FundingPaymentReportItemEventType = "Hourly Funding Transfer" +) + +// Valid indicates whether the value is a known member of the FundingPaymentReportItemEventType enum. +func (e FundingPaymentReportItemEventType) Valid() bool { + switch e { + case FundingPaymentReportItemEventTypeHourlyFundingTransfer: + return true + default: + return false + } +} + +// Defines values for FundingTransferAction. +const ( + FundingTransferActionCredit FundingTransferAction = "Credit" + FundingTransferActionDebit FundingTransferAction = "Debit" +) + +// Valid indicates whether the value is a known member of the FundingTransferAction enum. +func (e FundingTransferAction) Valid() bool { + switch e { + case FundingTransferActionCredit: + return true + case FundingTransferActionDebit: + return true + default: + return false + } +} + +// Defines values for InstantQuoteSide. +const ( + InstantQuoteSideBuy InstantQuoteSide = "buy" + InstantQuoteSideSell InstantQuoteSide = "sell" +) + +// Valid indicates whether the value is a known member of the InstantQuoteSide enum. +func (e InstantQuoteSide) Valid() bool { + switch e { + case InstantQuoteSideBuy: + return true + case InstantQuoteSideSell: + return true + default: + return false + } +} + +// Defines values for InterestRateInfoInterval. +const ( + Hour InterestRateInfoInterval = "hour" +) + +// Valid indicates whether the value is a known member of the InterestRateInfoInterval enum. +func (e InterestRateInfoInterval) Valid() bool { + switch e { + case Hour: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseSide. +const ( + LimitOrderResponseSideBuy LimitOrderResponseSide = "buy" + LimitOrderResponseSideSell LimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseSide enum. +func (e LimitOrderResponseSide) Valid() bool { + switch e { + case LimitOrderResponseSideBuy: + return true + case LimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for LimitOrderResponseType. +const ( + LimitOrderResponseTypeExchangeLimit LimitOrderResponseType = "exchange limit" + LimitOrderResponseTypeExchangeMarket LimitOrderResponseType = "exchange market" + LimitOrderResponseTypeExchangeStopLimit LimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the LimitOrderResponseType enum. +func (e LimitOrderResponseType) Valid() bool { + switch e { + case LimitOrderResponseTypeExchangeLimit: + return true + case LimitOrderResponseTypeExchangeMarket: + return true + case LimitOrderResponseTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for MyTradeBreak. +const ( + Empty MyTradeBreak = "" + TradeCorrect MyTradeBreak = "trade correct" +) + +// Valid indicates whether the value is a known member of the MyTradeBreak enum. +func (e MyTradeBreak) Valid() bool { + switch e { + case Empty: + return true + case TradeCorrect: + return true + default: + return false + } +} + +// Defines values for MyTradeType. +const ( + MyTradeTypeBuy MyTradeType = "Buy" + MyTradeTypeSell MyTradeType = "Sell" +) + +// Valid indicates whether the value is a known member of the MyTradeType enum. +func (e MyTradeType) Valid() bool { + switch e { + case MyTradeTypeBuy: + return true + case MyTradeTypeSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestOptions. +const ( + FillOrKill NewOrderRequestOptions = "fill-or-kill" + ImmediateOrCancel NewOrderRequestOptions = "immediate-or-cancel" + MakerOrCancel NewOrderRequestOptions = "maker-or-cancel" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestOptions enum. +func (e NewOrderRequestOptions) Valid() bool { + switch e { + case FillOrKill: + return true + case ImmediateOrCancel: + return true + case MakerOrCancel: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestSide. +const ( + NewOrderRequestSideBuy NewOrderRequestSide = "buy" + NewOrderRequestSideSell NewOrderRequestSide = "sell" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestSide enum. +func (e NewOrderRequestSide) Valid() bool { + switch e { + case NewOrderRequestSideBuy: + return true + case NewOrderRequestSideSell: + return true + default: + return false + } +} + +// Defines values for NewOrderRequestType. +const ( + NewOrderRequestTypeExchangeLimit NewOrderRequestType = "exchange limit" + NewOrderRequestTypeExchangeMarket NewOrderRequestType = "exchange market" + NewOrderRequestTypeExchangeStopLimit NewOrderRequestType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the NewOrderRequestType enum. +func (e NewOrderRequestType) Valid() bool { + switch e { + case NewOrderRequestTypeExchangeLimit: + return true + case NewOrderRequestTypeExchangeMarket: + return true + case NewOrderRequestTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for OrderSide. +const ( + OrderSideBuy OrderSide = "buy" + OrderSideSell OrderSide = "sell" +) + +// Valid indicates whether the value is a known member of the OrderSide enum. +func (e OrderSide) Valid() bool { + switch e { + case OrderSideBuy: + return true + case OrderSideSell: + return true + default: + return false + } +} + +// Defines values for OrderTradesType. +const ( + OrderTradesTypeBuy OrderTradesType = "Buy" + OrderTradesTypeSell OrderTradesType = "Sell" +) + +// Valid indicates whether the value is a known member of the OrderTradesType enum. +func (e OrderTradesType) Valid() bool { + switch e { + case OrderTradesTypeBuy: + return true + case OrderTradesTypeSell: + return true + default: + return false + } +} + +// Defines values for OrderType. +const ( + OrderTypeExchangeLimit OrderType = "exchange limit" + OrderTypeExchangeMarket OrderType = "exchange market" + OrderTypeExchangeStopLimit OrderType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the OrderType enum. +func (e OrderType) Valid() bool { + switch e { + case OrderTypeExchangeLimit: + return true + case OrderTypeExchangeMarket: + return true + case OrderTypeExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for RiskStatsResponseProductType. +const ( + PerpetualSwapContract RiskStatsResponseProductType = "PerpetualSwapContract" +) + +// Valid indicates whether the value is a known member of the RiskStatsResponseProductType enum. +func (e RiskStatsResponseProductType) Valid() bool { + switch e { + case PerpetualSwapContract: + return true + default: + return false + } +} + +// Defines values for StakingTransactionTransactionType. +const ( + StakingTransactionTransactionTypeAdminCreditAdjustment StakingTransactionTransactionType = "AdminCreditAdjustment" + StakingTransactionTransactionTypeAdminDebitAdjustment StakingTransactionTransactionType = "AdminDebitAdjustment" + StakingTransactionTransactionTypeAdminRedeem StakingTransactionTransactionType = "AdminRedeem" + StakingTransactionTransactionTypeDeposit StakingTransactionTransactionType = "Deposit" + StakingTransactionTransactionTypeInterest StakingTransactionTransactionType = "Interest" + StakingTransactionTransactionTypeRedeem StakingTransactionTransactionType = "Redeem" + StakingTransactionTransactionTypeRedeemPayment StakingTransactionTransactionType = "RedeemPayment" +) + +// Valid indicates whether the value is a known member of the StakingTransactionTransactionType enum. +func (e StakingTransactionTransactionType) Valid() bool { + switch e { + case StakingTransactionTransactionTypeAdminCreditAdjustment: + return true + case StakingTransactionTransactionTypeAdminDebitAdjustment: + return true + case StakingTransactionTransactionTypeAdminRedeem: + return true + case StakingTransactionTransactionTypeDeposit: + return true + case StakingTransactionTransactionTypeInterest: + return true + case StakingTransactionTransactionTypeRedeem: + return true + case StakingTransactionTransactionTypeRedeemPayment: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseSide. +const ( + StopLimitOrderResponseSideBuy StopLimitOrderResponseSide = "buy" + StopLimitOrderResponseSideSell StopLimitOrderResponseSide = "sell" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseSide enum. +func (e StopLimitOrderResponseSide) Valid() bool { + switch e { + case StopLimitOrderResponseSideBuy: + return true + case StopLimitOrderResponseSideSell: + return true + default: + return false + } +} + +// Defines values for StopLimitOrderResponseType. +const ( + ExchangeStopLimit StopLimitOrderResponseType = "exchange stop limit" +) + +// Valid indicates whether the value is a known member of the StopLimitOrderResponseType enum. +func (e StopLimitOrderResponseType) Valid() bool { + switch e { + case ExchangeStopLimit: + return true + default: + return false + } +} + +// Defines values for TradeType. +const ( + TradeTypeBuy TradeType = "buy" + TradeTypeSell TradeType = "sell" +) + +// Valid indicates whether the value is a known member of the TradeType enum. +func (e TradeType) Valid() bool { + switch e { + case TradeTypeBuy: + return true + case TradeTypeSell: + return true + default: + return false + } +} + +// Defines values for TransferStatus. +const ( + TransferStatusComplete TransferStatus = "Complete" + TransferStatusPending TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the TransferStatus enum. +func (e TransferStatus) Valid() bool { + switch e { + case TransferStatusComplete: + return true + case TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for TransferType. +const ( + TransferTypeDeposit TransferType = "Deposit" + TransferTypeWithdrawal TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the TransferType enum. +func (e TransferType) Valid() bool { + switch e { + case TransferTypeDeposit: + return true + case TransferTypeWithdrawal: + return true + default: + return false + } +} + +// Defines values for V2TransferStatus. +const ( + V2TransferStatusAdvanced V2TransferStatus = "Advanced" + V2TransferStatusComplete V2TransferStatus = "Complete" + V2TransferStatusPending V2TransferStatus = "Pending" +) + +// Valid indicates whether the value is a known member of the V2TransferStatus enum. +func (e V2TransferStatus) Valid() bool { + switch e { + case V2TransferStatusAdvanced: + return true + case V2TransferStatusComplete: + return true + case V2TransferStatusPending: + return true + default: + return false + } +} + +// Defines values for V2TransferType. +const ( + AdminCredit V2TransferType = "AdminCredit" + AdminDebit V2TransferType = "AdminDebit" + Deposit V2TransferType = "Deposit" + Reward V2TransferType = "Reward" + Withdrawal V2TransferType = "Withdrawal" +) + +// Valid indicates whether the value is a known member of the V2TransferType enum. +func (e V2TransferType) Valid() bool { + switch e { + case AdminCredit: + return true + case AdminDebit: + return true + case Deposit: + return true + case Reward: + return true + case Withdrawal: + return true + default: + return false + } +} + +// Defines values for WrapOrderJSONBodySide. +const ( + Buy WrapOrderJSONBodySide = "buy" + Sell WrapOrderJSONBodySide = "sell" +) + +// Valid indicates whether the value is a known member of the WrapOrderJSONBodySide enum. +func (e WrapOrderJSONBodySide) Valid() bool { + switch e { + case Buy: + return true + case Sell: + return true + default: + return false + } +} + +// Account defines model for Account. +type Account struct { + // AccountId The account ID + AccountId *string `json:"account_id,omitempty"` + + // Created The creation date + Created *string `json:"created,omitempty"` + + // IsDefault Whether the account is the default account + IsDefault *bool `json:"is_default,omitempty"` + + // Name The account name + Name *string `json:"name,omitempty"` +} + +// AddBankResponse defines model for AddBankResponse. +type AddBankResponse struct { + // ReferenceId Reference ID for the new bank addition request. Once received, send in a wire from the requested bank account to verify it and enable withdrawals to that account. + ReferenceId *string `json:"referenceId,omitempty"` + + // Result Status result (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// Address defines model for Address. +type Address struct { + // Address String representation of the cryptocurrency address + Address *string `json:"address,omitempty"` + + // Label If you provided a label when creating the address, it will be echoed back here + Label *string `json:"label,omitempty"` + + // Memo It would be present if applicable, it will be present for cosmos address + Memo *string `json:"memo,omitempty"` + + // Network The blockchain network for the address + Network *string `json:"network,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ApprovedAddress defines model for ApprovedAddress. +type ApprovedAddress struct { + // Address The address on the approved address list. + Address *string `json:"address,omitempty"` + + // CreatedAt UTC timestamp in millisecond of when the address was created. + CreatedAt *string `json:"createdAt,omitempty"` + + // Label The label assigned to the address + Label *string `json:"label,omitempty"` + + // Network The network of the approved address. Network can be `bitcoin`, `ethereum`, `bitcoincash`, `litecoin`, `zcash`, `filecoin`, `dogecoin`, `tezos`, `solana`, `polkadot`, `avalanche`, `cosmos`, or `xrpl` + Network *string `json:"network,omitempty"` + + // Scope Will return the scope of the address as either "account" or "group" + Scope *string `json:"scope,omitempty"` + + // Status The status of the address that will return as "active", "pending-time" or "pending-mua". The remaining time is exactly 7 days after the initial request. "pending-mua" is for multi-user accounts and will require another administator or fund manager on the account to approve the address. + Status *string `json:"status,omitempty"` +} + +// ApprovedAddressMessage defines model for ApprovedAddressMessage. +type ApprovedAddressMessage struct { + // Message Status or confirmation message for the approved address request or removal. + Message *string `json:"message,omitempty"` + + // Result Result status (e.g. ok). + Result *string `json:"result,omitempty"` +} + +// ApprovedAddressesResponse Response envelope containing the approved withdrawal addresses. +type ApprovedAddressesResponse struct { + // ApprovedAddresses Array of approved addresses on both the account and group level. + ApprovedAddresses *[]ApprovedAddress `json:"approvedAddresses,omitempty"` +} + +// Balance defines model for Balance. +type Balance struct { + // UnderscoreTimestamp Server-side monotonically increasing clock value as an ISO 8601 timestamp. Clients can use this value to detect and filter out stale responses that may occur due to load balancing or potential stale servers. + UnderscoreTimestamp *time.Time `json:"_timestamp,omitempty"` + + // Amount The confirmed balance for the currency (also referred to as `confirmedBalance`). For crypto withdrawals, this value is **not** reduced until the withdrawal has been confirmed on the blockchain. This delay protects against blockchain reorganizations. Use the `available` field instead if you need balances that immediately reflect holds. + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Available The amount available for trading. This value is reduced **immediately** when an order hold or withdrawal hold is placed, making it the recommended field for tracking real-time spendable balances. + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The amount available for withdrawal + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Currency The currency symbol + Currency *string `json:"currency,omitempty"` + + // PendingDeposit The amount pending deposit + PendingDeposit *openapi_types.DecimalNumber `json:"pendingDeposit,omitempty"` + + // PendingWithdrawal The amount pending withdrawal + PendingWithdrawal *openapi_types.DecimalNumber `json:"pendingWithdrawal,omitempty"` + Type *BalanceType `json:"type,omitempty"` +} + +// BalanceType defines model for Balance.Type. +type BalanceType string + +// CancelAllOrdersBySessionRequest defines model for CancelAllOrdersBySessionRequest. +type CancelAllOrdersBySessionRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/session" + Request string `json:"request"` +} + +// CancelAllOrdersRequest defines model for CancelAllOrdersRequest. +type CancelAllOrdersRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the orders. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The literal string "/v1/order/cancel/all" + Request string `json:"request"` +} + +// CancelAllResult defines model for CancelAllResult. +type CancelAllResult struct { + // Details cancelledOrders/cancelRejects with IDs of both + Details *struct { + CancelRejects *[]int64 `json:"cancelRejects,omitempty"` + CancelledOrders *[]int64 `json:"cancelledOrders,omitempty"` + } `json:"details,omitempty"` + Result *string `json:"result,omitempty"` +} + +// CancelOrderRequest defines model for CancelOrderRequest. +type CancelOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to cancel the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order ID given by `/order/new` + OrderId uint64 `json:"order_id"` + + // Request The literal string "/v1/order/cancel" + Request string `json:"request"` +} + +// CancelOrderResponse defines model for CancelOrderResponse. +type CancelOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Reason *CancelOrderResponseReason `json:"reason,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *CancelOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *CancelOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// CancelOrderResponseReason defines model for CancelOrderResponse.Reason. +type CancelOrderResponseReason string + +// CancelOrderResponseSide defines model for CancelOrderResponse.Side. +type CancelOrderResponseSide string + +// CancelOrderResponseType defines model for CancelOrderResponse.Type. +type CancelOrderResponseType string + +// Candle defines model for Candle. +type Candle = []float64 + +// CandleResponse defines model for CandleResponse. +type CandleResponse = []Candle + +// ClearingOrder defines model for ClearingOrder. +type ClearingOrder struct { + // Amount The order amount + Amount *string `json:"amount,omitempty"` + + // ClearingId The clearing ID + ClearingId *string `json:"clearing_id,omitempty"` + + // IsConfirmed Whether the order is confirmed + IsConfirmed *bool `json:"is_confirmed,omitempty"` + + // Price The order price + Price *string `json:"price,omitempty"` + Side *ClearingOrderSide `json:"side,omitempty"` + + // Status The order status + Status *string `json:"status,omitempty"` + + // Symbol The trading pair + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms The timestamp in milliseconds + Timestampms *int64 `json:"timestampms,omitempty"` +} + +// ClearingOrderSide defines model for ClearingOrder.Side. +type ClearingOrderSide string + +// CustodyFeeTransfer defines model for CustodyFeeTransfer. +type CustodyFeeTransfer struct { + // Eid Custody fee event id + Eid *int64 `json:"eid,omitempty"` + + // EventType Custody fee event type + EventType *string `json:"eventType,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // TxTime Time of Custody fee record in milliseconds + TxTime *int64 `json:"txTime,omitempty"` +} + +// ErrorResponse defines model for ErrorResponse. +type ErrorResponse struct { + // Message Detailed error message + Message *string `json:"message,omitempty"` + + // Reason A short description + Reason *string `json:"reason,omitempty"` + + // Result Error + Result *string `json:"result,omitempty"` +} + +// FeeEstimateRequest defines model for FeeEstimateRequest. +type FeeEstimateRequest struct { + // Account The name of the account within the subaccount group. + Account string `json:"account"` + + // Address Standard string format of cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v1/withdraw/{currencyCodeLowerCase}/feeEstimate` where `:currencyCodeLowerCase` is replaced with the currency code of a supported crypto-currency, e.g. `eth`, `aave`, etc. See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateResponse defines model for FeeEstimateResponse. +type FeeEstimateResponse struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated gas fee + Fee *string `json:"fee,omitempty"` + + // IsOverride Value that shows if an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total nunber of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals left to use + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeeEstimateV2Request defines model for FeeEstimateV2Request. +type FeeEstimateV2Request struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Address Standard string format of the destination cryptocurrency address + Address string `json:"address"` + + // Amount Quoted decimal amount to withdraw + Amount string `json:"amount"` + + // Memo It would be present if applicable, it will be present for cosmos address. + Memo *string `json:"memo,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The string `/v2/withdraw/{network}/{ticker}/feeEstimate` where `{network}` is the blockchain network (e.g. `ethereum`, `bitcoin`, `solana`) and `{ticker}` is the currency code (e.g. `eth`, `btc`, `sol`). See [Symbols and minimums](/market-data/symbols-and-minimums) + Request string `json:"request"` +} + +// FeeEstimateV2Response defines model for FeeEstimateV2Response. +type FeeEstimateV2Response struct { + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums). + Currency *string `json:"currency,omitempty"` + + // Fee The estimated withdrawal fee as a decimal amount + Fee *openapi_types.DecimalNumber `json:"fee,omitempty"` + + // IsOverride Whether an override on the customer's account for free withdrawals exists + IsOverride *bool `json:"isOverride,omitempty"` + + // MonthlyLimit Total number of allowable fee-free withdrawals + MonthlyLimit *int `json:"monthlyLimit,omitempty"` + + // MonthlyRemaining Total number of allowable fee-free withdrawals remaining + MonthlyRemaining *int `json:"monthlyRemaining,omitempty"` +} + +// FeePromos defines model for FeePromos. +type FeePromos struct { + // Symbols Symbols that currently have fee promos + Symbols *[]string `json:"symbols,omitempty"` +} + +// FundingAmountResponse defines model for FundingAmountResponse. +type FundingAmountResponse struct { + // Amount The dollar amount for a Long 1 position held in the symbol for funding period (1 hour) + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // EstimatedFundingAmount The estimated dollar amount for a Long 1 position held in the symbol for next funding period (1 hour) + EstimatedFundingAmount *openapi_types.DecimalNumber `json:"estimatedFundingAmount,omitempty"` + + // FundingDateTime UTC date time in format `yyyy-MM-ddThh:mm:ss.SSSZ` format + FundingDateTime *string `json:"fundingDateTime,omitempty"` + + // FundingTimestampMilliSecs Current funding amount Epoc time. + FundingTimestampMilliSecs *int64 `json:"fundingTimestampMilliSecs,omitempty"` + + // NextFundingTimestamp Next funding amount Epoc time. + NextFundingTimestamp *int64 `json:"nextFundingTimestamp,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` +} + +// FundingPayment defines model for FundingPayment. +type FundingPayment struct { + // EventType Event type + EventType FundingPaymentEventType `json:"eventType"` + HourlyFundingTransfer FundingTransfer `json:"hourlyFundingTransfer"` +} + +// FundingPaymentEventType Event type +type FundingPaymentEventType string + +// FundingPaymentReportItem defines model for FundingPaymentReportItem. +type FundingPaymentReportItem struct { + // Action Credit or Debit + Action FundingPaymentReportItemAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType FundingPaymentReportItemEventType `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingPaymentReportItemAction Credit or Debit +type FundingPaymentReportItemAction string + +// FundingPaymentReportItemEventType Event type +type FundingPaymentReportItemEventType string + +// FundingTransfer defines model for FundingTransfer. +type FundingTransfer struct { + // Action Credit or Debit + Action FundingTransferAction `json:"action"` + + // AssetCode Asset symbol + AssetCode string `json:"assetCode"` + + // EventType Event type + EventType string `json:"eventType"` + + // InstrumentSymbol Symbol of the underlying instrument. **Note** that this is only attached to requests from 16th April 2024 onwards. + InstrumentSymbol *string `json:"instrumentSymbol,omitempty"` + + // Quantity A nested JSON object describing the transaction amount + Quantity Quantity `json:"quantity"` + + // Timestamp Time of the funding payment + Timestamp TimestampType `json:"timestamp"` +} + +// FundingTransferAction Credit or Debit +type FundingTransferAction string + +// FxRate defines model for FxRate. +type FxRate struct { + // AsOf timestamp + AsOf *TimestampType `json:"asOf,omitempty"` + + // Benchmark The market for which the retrieved price applies to + Benchmark *string `json:"benchmark,omitempty"` + + // FxPair The requested currency pair + FxPair *string `json:"fxPair,omitempty"` + + // Provider The market data provider + Provider *string `json:"provider,omitempty"` + + // Rate The exchange rate + Rate *float64 `json:"rate,omitempty"` +} + +// Heartbeat defines model for Heartbeat. +type Heartbeat struct { + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce *Heartbeat_Nonce `json:"nonce,omitempty"` + + // Request The literal string `/v1/heartbeat` + Request *string `json:"request,omitempty"` +} + +// HeartbeatNonce0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `'1495127793'` | `POST` only | +// | string (milliseconds) | `'1495127793000'` | `POST` only | +type HeartbeatNonce0 = string + +// HeartbeatNonce1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type HeartbeatNonce1 = int64 + +// Heartbeat_Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Heartbeat_Nonce struct { + union json.RawMessage +} + +// InstantQuote defines model for InstantQuote. +type InstantQuote struct { + // DepositFee The deposit fee quantity. Will be applied if a debit card is used for the order. Will return 0 if there is no `depositFee` + DepositFee *string `json:"depositFee,omitempty"` + + // DepositFeeCurrency Currency in which `depositFee` is taken + DepositFeeCurrency *string `json:"depositFeeCurrency,omitempty"` + + // Fee The fee quantity to be taken for the order upon execution + Fee *string `json:"fee,omitempty"` + + // FeeCurrency The currency label for the order + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // MaxAgeMs Number of milliseconds until this quote price expires. Once expired, you will need to request a new quote + MaxAgeMs *int `json:"maxAgeMs,omitempty"` + + // Pair The symbol passed in the quote request + Pair *string `json:"pair,omitempty"` + + // Price The quoted price of the asset. This will not change when attempting execution + Price *string `json:"price,omitempty"` + + // PriceCurrency The currency in which the order is priced. Matches `CCY2` in the symbol + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // Quantity The quantity of the asset to be bought or sold + Quantity *string `json:"quantity,omitempty"` + + // QuantityCurrency The currency label for the `quantity` field. Matches `CCY1` in the symbol + QuantityCurrency *string `json:"quantityCurrency,omitempty"` + + // QuoteId Unique ID for the quote. This is used in the execution of the order + QuoteId *int64 `json:"quoteId,omitempty"` + + // Side Either "buy" or "sell" + Side *InstantQuoteSide `json:"side,omitempty"` + + // TotalSpend Total quantity to spend for the order. Will be the sum inclusive of all fees and amount to be traded. + TotalSpend *string `json:"totalSpend,omitempty"` + + // TotalSpendCurrency Currency of the `totalSpend` to be spent on the order + TotalSpendCurrency *string `json:"totalSpendCurrency,omitempty"` +} + +// InstantQuoteSide Either "buy" or "sell" +type InstantQuoteSide string + +// InterestRateInfo defines model for InterestRateInfo. +type InterestRateInfo struct { + // Interval The time interval for the rate (currently only "hour" is supported) + Interval InterestRateInfoInterval `json:"interval"` + + // Rate The interest rate as a decimal string + Rate string `json:"rate"` +} + +// InterestRateInfoInterval The time interval for the rate (currently only "hour" is supported) +type InterestRateInfoInterval string + +// LimitOrderResponse defines model for LimitOrderResponse. +type LimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *LimitOrderResponseSide `json:"side,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *LimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// LimitOrderResponseSide defines model for LimitOrderResponse.Side. +type LimitOrderResponseSide string + +// LimitOrderResponseType defines model for LimitOrderResponse.Type. +type LimitOrderResponseType string + +// LiquidationRisk defines model for LiquidationRisk. +type LiquidationRisk struct { + // LiquidationPrice The estimated price at which liquidation would occur (optional, may not be present for all positions) + LiquidationPrice *MoneyAmount `json:"liquidationPrice,omitempty"` + + // LossPercentage The percentage loss from current value that would trigger liquidation, formatted as decimal (e.g., "0.1550" = 15.50%) + LossPercentage string `json:"lossPercentage"` +} + +// MarginAccountSummary defines model for MarginAccountSummary. +type MarginAccountSummary struct { + // AvailableCollateral The amount of collateral available for new positions or withdrawals + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased with available collateral + BuyingPower MoneyAmount `json:"buyingPower"` + + // InterestRate Current interest rate on borrowed amounts (only present if borrows exist) + InterestRate *InterestRateInfo `json:"interestRate,omitempty"` + + // Leverage The current leverage ratio (notionalValue / marginAssetValue) + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if positions exist) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account that can contribute to funding positions + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold with available collateral + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed across all currencies + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MarginInterestRate defines model for MarginInterestRate. +type MarginInterestRate struct { + // BorrowRate The hourly borrow rate as a decimal + BorrowRate string `json:"borrowRate"` + + // BorrowRateAnnual The annualized borrow rate (daily rate × 365) + BorrowRateAnnual string `json:"borrowRateAnnual"` + + // BorrowRateDaily The daily borrow rate (hourly rate × 24) + BorrowRateDaily string `json:"borrowRateDaily"` + + // Currency The currency code (e.g., "BTC", "ETH", "USD") + Currency string `json:"currency"` + + // LastUpdated Unix timestamp in milliseconds when the rate was last updated + LastUpdated int64 `json:"lastUpdated"` +} + +// MarginOrderPreview defines model for MarginOrderPreview. +type MarginOrderPreview struct { + // Postorder Margin risk statistics after the order would be executed + Postorder MarginRiskStats `json:"postorder"` + + // Preorder Margin risk statistics before the order would be executed + Preorder MarginRiskStats `json:"preorder"` +} + +// MarginRatesResponse defines model for MarginRatesResponse. +type MarginRatesResponse struct { + // Rates Array of interest rates for all borrowable currencies + Rates []MarginInterestRate `json:"rates"` +} + +// MarginResponse defines model for MarginResponse. +type MarginResponse struct { + // AvailableMargin The difference between the `margin_assets_value` and `initial_margin`. + AvailableMargin *string `json:"available_margin,omitempty"` + + // BuyingPower The amount of that product the account could purchase based on current `initial_margin` and `margin_assets_value`. + BuyingPower *string `json:"buying_power,omitempty"` + + // EstimatedLiquidationPrice The estimated price for the asset at which liquidation would occur. + EstimatedLiquidationPrice *string `json:"estimated_liquidation_price,omitempty"` + + // InitialMargin The $ amount that is being required by the accounts current positions and open orders. + InitialMargin *string `json:"initial_margin,omitempty"` + + // InitialMarginPositions The contribution to `initial_margin` from open positions. + InitialMarginPositions *string `json:"initial_margin_positions,omitempty"` + + // Leverage The ratio of Notional Value to Margin Assets Value. + Leverage *string `json:"leverage,omitempty"` + + // MarginAssetsValue The $ equivalent value of all the assets available in the current trading account that can contribute to funding a derivatives position. + MarginAssetsValue *string `json:"margin_assets_value,omitempty"` + + // MarginMaintenanceLimit The minimum amount of `margin_assets_value` required before the account is moved to liquidation status. + MarginMaintenanceLimit *string `json:"margin_maintenance_limit,omitempty"` + + // NotionalValue The $ value of the current position. + NotionalValue *string `json:"notional_value,omitempty"` + + // ReservedMargin The contribution to `initial_margin` from open orders. + ReservedMargin *string `json:"reserved_margin,omitempty"` + + // ReservedMarginBuys The contribution to `initial_margin` from open BUY orders. + ReservedMarginBuys *string `json:"reserved_margin_buys,omitempty"` + + // ReservedMarginSells The contribution to `initial_margin` from open SELL orders. + ReservedMarginSells *string `json:"reserved_margin_sells,omitempty"` + + // SellingPower The amount of that product the account could sell based on current `initial_margin` and `margin_assets_value`. + SellingPower *string `json:"selling_power,omitempty"` +} + +// MarginRiskStats defines model for MarginRiskStats. +type MarginRiskStats struct { + // AvailableCollateral The amount of collateral available for new positions + AvailableCollateral MoneyAmount `json:"availableCollateral"` + + // BuyingPower The maximum value that can be purchased + BuyingPower MoneyAmount `json:"buyingPower"` + + // Leverage The leverage ratio + Leverage string `json:"leverage"` + + // LiquidationRisk Liquidation risk information (only present if applicable) + LiquidationRisk *LiquidationRisk `json:"liquidationRisk,omitempty"` + + // MarginAssetValue The total value of all assets available in the margin account + MarginAssetValue MoneyAmount `json:"marginAssetValue"` + + // NotionalValue The total value of all open positions + NotionalValue MoneyAmount `json:"notionalValue"` + + // ReservedBuyOrders Collateral reserved for open buy orders + ReservedBuyOrders MoneyAmount `json:"reservedBuyOrders"` + + // ReservedSellOrders Collateral reserved for open sell orders + ReservedSellOrders MoneyAmount `json:"reservedSellOrders"` + + // SellingPower The maximum value that can be sold + SellingPower MoneyAmount `json:"sellingPower"` + + // TotalBorrowed The total amount currently borrowed + TotalBorrowed MoneyAmount `json:"totalBorrowed"` +} + +// MoneyAmount defines model for MoneyAmount. +type MoneyAmount struct { + // Currency The currency code (e.g., "USD", "BTC", "ETH") + Currency string `json:"currency"` + + // Value The amount in the specified currency + Value string `json:"value"` +} + +// MyTrade defines model for MyTrade. +type MyTrade struct { + Aggressor *bool `json:"aggressor,omitempty"` + Amount *string `json:"amount,omitempty"` + Break *MyTradeBreak `json:"break,omitempty"` + ClientOrderId *string `json:"client_order_id,omitempty"` + Exchange *string `json:"exchange,omitempty"` + FeeAmount *string `json:"fee_amount,omitempty"` + FeeCurrency *string `json:"fee_currency,omitempty"` + IsAuctionFill *bool `json:"is_auction_fill,omitempty"` + OrderId *string `json:"order_id,omitempty"` + Price *string `json:"price,omitempty"` + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *MyTradeType `json:"type,omitempty"` +} + +// MyTradeBreak defines model for MyTrade.Break. +type MyTradeBreak string + +// MyTradeType defines model for MyTrade.Type. +type MyTradeType string + +// MyTradesRequest defines model for MyTradesRequest. +type MyTradesRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // LimitTrades The maximum number of trades to return. Default is 50, max is 500. + LimitTrades *int `json:"limit_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) to retrieve trades for + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// NetworkAssets defines model for NetworkAssets. +type NetworkAssets struct { + // Assets Alphabetically sorted array of enabled asset/token codes available on this network. Assets include both exchange-tradable and custody-supported tokens. + Assets *[]string `json:"assets,omitempty"` + + // Network The blockchain network identifier. + Network *string `json:"network,omitempty"` +} + +// NetworkToken defines model for NetworkToken. +type NetworkToken struct { + // Network Array of supported blockchain networks for the token. Many tokens (especially stablecoins like USDC, USDT) are available on multiple networks. + // + // Supported networks include: `bitcoin`, `ethereum`, `solana`, `optimism`, `arbitrum`, `base`, `monad`, `avalanche`, `litecoin`, `bitcoincash`, `dogecoin`, `zcash`, `filecoin`, `tezos`, `polkadot`, `cosmos`, `xrpl`, `linea`, and more. + Network *[]string `json:"network,omitempty"` + + // Token The requested token identifier. + Token *string `json:"token,omitempty"` +} + +// NewOrderRequest defines model for NewOrderRequest. +type NewOrderRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Amount Quoted decimal amount to purchase + Amount string `json:"amount"` + + // ClientOrderId *Recommended*. A [client-specified order id](/client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // MarginOrder Set to `true` to place this order on a margin account using borrowed funds. Defaults to `false`. Only available for margin-enabled accounts. See [Margin Trading](/margin/account-summary) for details. + MarginOrder *bool `json:"margin_order,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce int64 `json:"nonce"` + + // Options An optional array containing at most one supported order execution option. See Order execution options for details. + Options *[]NewOrderRequestOptions `json:"options,omitempty"` + + // Price Quoted decimal amount to spend per unit + Price string `json:"price"` + + // Request The literal string "/v1/order/new" + Request string `json:"request"` + Side NewOrderRequestSide `json:"side"` + + // StopPrice The price to trigger a stop-limit order. Only available for stop-limit orders. + StopPrice *string `json:"stop_price,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) for the new order + Symbol string `json:"symbol"` + + // Type The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. + Type NewOrderRequestType `json:"type"` +} + +// NewOrderRequestOptions defines model for NewOrderRequest.Options. +type NewOrderRequestOptions string + +// NewOrderRequestSide defines model for NewOrderRequest.Side. +type NewOrderRequestSide string + +// NewOrderRequestType The order type. "exchange limit" for all order types except for stop-limit orders. "exchange stop limit" for stop-limit orders. +type NewOrderRequestType string + +// Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) +type Nonce struct { + union json.RawMessage +} + +// Nonce1 defines model for . +type Nonce1 = int64 + +// NotionalBalance defines model for NotionalBalance. +type NotionalBalance struct { + // Amount The current balance + Amount *string `json:"amount,omitempty"` + + // AmountNotional Amount, in notional + AmountNotional *string `json:"amountNotional,omitempty"` + + // Available The amount that is available to trade + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal The amount that is available to withdraw + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // AvailableForWithdrawalNotional AvailableForWithdrawal, in notional + AvailableForWithdrawalNotional *string `json:"availableForWithdrawalNotional,omitempty"` + + // AvailableNotional Available, in notional + AvailableNotional *string `json:"availableNotional,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` +} + +// NotionalVolume defines model for NotionalVolume. +type NotionalVolume struct { + ApiAuctionFeeBps *int `json:"api_auction_fee_bps,omitempty"` + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiNotional30dVolume *string `json:"api_notional_30d_volume,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Date *openapi_types.Date `json:"date,omitempty"` + FeeTier *struct { + ApiMakerFeeBps *int `json:"api_maker_fee_bps,omitempty"` + ApiTakerFeeBps *int `json:"api_taker_fee_bps,omitempty"` + Tier *string `json:"tier,omitempty"` + } `json:"fee_tier,omitempty"` + FixAuctionFeeBps *int `json:"fix_auction_fee_bps,omitempty"` + FixMakerFeeBps *int `json:"fix_maker_fee_bps,omitempty"` + FixTakerFeeBps *int `json:"fix_taker_fee_bps,omitempty"` + LastUpdatedMs *int64 `json:"last_updated_ms,omitempty"` + Notional1dVolume *[]struct { + // Date UTC date in `yyyy-MM-dd` format + Date *string `json:"date,omitempty"` + + // NotionalVolume Notional volume value in USD for this single day + NotionalVolume *string `json:"notional_volume,omitempty"` + } `json:"notional_1d_volume,omitempty"` + Notional30dVolume *string `json:"notional_30d_volume,omitempty"` + WebAuctionFeeBps *int `json:"web_auction_fee_bps,omitempty"` + WebMakerFeeBps *int `json:"web_maker_fee_bps,omitempty"` + WebTakerFeeBps *int `json:"web_taker_fee_bps,omitempty"` +} + +// OpenPosition defines model for OpenPosition. +type OpenPosition struct { + // AverageCost The average price of the current position. + AverageCost *string `json:"average_cost,omitempty"` + + // InstrumentType The type of instrument. Either "spot" or "perp". + InstrumentType *string `json:"instrument_type,omitempty"` + + // MarkPrice The current Mark Price for the Asset or the position. + MarkPrice *string `json:"mark_price,omitempty"` + + // NotionalValue The value of position; calculated as (`quantity` * `mark_price`). Value will be negative for shorts. + NotionalValue *string `json:"notional_value,omitempty"` + + // Quantity The position size. Value will be negative for shorts. + Quantity *string `json:"quantity,omitempty"` + + // RealisedPnl The current P&L that has been realised from the position. + RealisedPnl *string `json:"realised_pnl,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums) of the order. + Symbol *string `json:"symbol,omitempty"` + + // UnrealisedPnl Current Mark to Market value of the positions. + UnrealisedPnl *string `json:"unrealised_pnl,omitempty"` +} + +// Order defines model for Order. +type Order struct { + // AvgExecutionPrice The average price at which this order as been executed so far. 0 if the order has not been executed at all. + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + + // ClientOrderId An optional [client-specified order id](/client-order-id#client-order-id) + ClientOrderId *string `json:"client_order_id,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // ExecutedAmount The amount of the order that has been filled. + ExecutedAmount *string `json:"executed_amount,omitempty"` + + // IsCancelled `true` if the order has been canceled. Note the spelling, "cancelled" instead of "canceled". This is for compatibility reasons. + IsCancelled *bool `json:"is_cancelled,omitempty"` + + // IsHidden Will always return `false`. + IsHidden *bool `json:"is_hidden,omitempty"` + + // IsLive `true` if the order is active on the book (has remaining quantity and has not been canceled) + IsLive *bool `json:"is_live,omitempty"` + + // Options An array containing at most one supported order execution option. See [Order execution options](/rest/orders#create-new-order) for details. + Options *[]string `json:"options,omitempty"` + + // OrderId The order id + OrderId *string `json:"order_id,omitempty"` + + // OriginalAmount The originally submitted amount of the order. + OriginalAmount *string `json:"original_amount,omitempty"` + + // Price The price the order was issued at + Price *string `json:"price,omitempty"` + + // Reason Populated with the reason your order was canceled, if available. + Reason *string `json:"reason,omitempty"` + + // RemainingAmount The amount of the order that has not been filled. + RemainingAmount *string `json:"remaining_amount,omitempty"` + Side *OrderSide `json:"side,omitempty"` + + // Symbol The [symbol](/market-data/symbols-and-minimums#symbols-and-minimums) of the order + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Trades Contains an array of JSON objects with trade details. + Trades *[]struct { + // Aggressor If `true`, this order was the taker in the trade + Aggressor *bool `json:"aggressor,omitempty"` + + // Amount The quantity that was executed + Amount *string `json:"amount,omitempty"` + + // Break Will only be present if the trade is broken. See `Break Types` below for more information. + Break *string `json:"break,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The amount charged + FeeAmount *string `json:"fee_amount,omitempty"` + + // FeeCurrency Currency that the fee was paid in + FeeCurrency *string `json:"fee_currency,omitempty"` + + // OrderId The order that this trade executed against + OrderId *string `json:"order_id,omitempty"` + + // Price The price that the execution happened at + Price *string `json:"price,omitempty"` + + // Tid Unique identifier for the trade + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type Will be either "Buy" or "Sell", indicating the side of the original order + Type *OrderTradesType `json:"type,omitempty"` + } `json:"trades,omitempty"` + + // Type Description of the order + Type *OrderType `json:"type,omitempty"` + + // WasForced Will always be `false`. + WasForced *bool `json:"was_forced,omitempty"` +} + +// OrderSide defines model for Order.Side. +type OrderSide string + +// OrderTradesType Will be either "Buy" or "Sell", indicating the side of the original order +type OrderTradesType string + +// OrderType Description of the order +type OrderType string + +// OrderBook defines model for OrderBook. +type OrderBook struct { + // Asks The ask price levels currently on the book. These are offers to sell at a given price. + Asks *[]OrderBookEntry `json:"asks,omitempty"` + + // Bids The bid price levels currently on the book. These are offers to buy at a given price. + Bids *[]OrderBookEntry `json:"bids,omitempty"` +} + +// OrderBookEntry defines model for OrderBookEntry. +type OrderBookEntry struct { + // Amount The total quantity remaining at the price + Amount *string `json:"amount,omitempty"` + + // Price The price + Price *string `json:"price,omitempty"` + + // Timestamp **DO NOT USE** - this field is included for compatibility reasons only and is just populated with a dummy value. + Timestamp *string `json:"timestamp,omitempty"` +} + +// OrderStatusRequest defines model for OrderStatusRequest. +type OrderStatusRequest struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // ClientOrderId The `client_order_id` used when placing the order. `client_order_id` cannot be used in combination with `order_id` + ClientOrderId *string `json:"client_order_id,omitempty"` + + // IncludeTrades Either `True` or `False`. If `True` the endpoint will return individual trade details of all fills from the order. + IncludeTrades *bool `json:"include_trades,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // OrderId The order id to get information on. The `order_id` represents a whole number and is transmitted as an unsigned 64-bit integer in JSON format. `order_id` cannot be used in combination with `client_order_id`. + OrderId uint64 `json:"order_id"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// PaymentMethodBalance defines model for PaymentMethodBalance. +type PaymentMethodBalance struct { + // Amount Total account balance for currency. + Amount *string `json:"amount,omitempty"` + + // Available Total amount available for trading + Available *string `json:"available,omitempty"` + + // AvailableForWithdrawal Total amount available for withdrawal + AvailableForWithdrawal *string `json:"availableForWithdrawal,omitempty"` + + // Currency Symbol for fiat balance. + Currency *string `json:"currency,omitempty"` + + // Type Account type. Will always be `exchange` + Type *string `json:"type,omitempty"` +} + +// PaymentMethodBank defines model for PaymentMethodBank. +type PaymentMethodBank struct { + // Bank Name of bank account + Bank *string `json:"bank,omitempty"` + + // BankId Unique identifier for bank account + BankId *string `json:"bankId,omitempty"` +} + +// PaymentMethodsResponse defines model for PaymentMethodsResponse. +type PaymentMethodsResponse struct { + // Balances Array of JSON objects with available fiat currencies and their balances. + Balances *[]PaymentMethodBalance `json:"balances,omitempty"` + + // Banks Array of JSON objects with banking information + Banks *[]PaymentMethodBank `json:"banks,omitempty"` +} + +// PriceFeedResponse defines model for PriceFeedResponse. +type PriceFeedResponse = []struct { + // Pair Trading pair symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Pair *string `json:"pair,omitempty"` + + // PercentChange24h 24 hour change in price of the pair on the Gemini order book + PercentChange24h *string `json:"percentChange24h,omitempty"` + + // Price Current price of the pair on the Gemini order book + Price *string `json:"price,omitempty"` +} + +// Quantity defines model for Quantity. +type Quantity struct { + // Currency The currency code of the quantity. + Currency string `json:"currency"` + + // Value The value of the quantity. + Value string `json:"value"` +} + +// RevokeOauthTokenResponse defines model for RevokeOauthTokenResponse. +type RevokeOauthTokenResponse struct { + // Message A message that indicates the token has been revoked for the account + Message *string `json:"message,omitempty"` +} + +// RiskStatsResponse defines model for RiskStatsResponse. +type RiskStatsResponse struct { + // IndexPrice Current index price at the time of request + IndexPrice *string `json:"index_price,omitempty"` + + // MarkPrice Current mark price at the time of request + MarkPrice *string `json:"mark_price,omitempty"` + + // OpenInterest string representation of decimal value of open interest + OpenInterest *string `json:"open_interest,omitempty"` + + // OpenInterestNotional string representation of decimal value of open interest notional + OpenInterestNotional *string `json:"open_interest_notional,omitempty"` + + // ProductType Contract type for which the symbol data is fetched + ProductType *RiskStatsResponseProductType `json:"product_type,omitempty"` +} + +// RiskStatsResponseProductType Contract type for which the symbol data is fetched +type RiskStatsResponseProductType string + +// RoleResponse defines model for RoleResponse. +type RoleResponse struct { + // CounterpartyId _Only returned for master-level API keys_. The Gemini clearing counterparty ID associated with the API key making the request. + CounterpartyId *string `json:"counterparty_id,omitempty"` + + // IsAccountAdmin _Only returned for master-level API keys_.`True` if the Administrator role is assigned to the API keys. `False` otherwise. + IsAccountAdmin *bool `json:"isAccountAdmin,omitempty"` + + // IsAuditor `True` if the Auditor role is assigned to the API keys. `False` otherwise. + IsAuditor bool `json:"isAuditor"` + + // IsFundManager `True` if the Fund Manager role is assigned to the API keys. `False` otherwise. + IsFundManager bool `json:"isFundManager"` + + // IsTrader `True` if the Trader role is assigned to the API keys. `False` otherwise. + IsTrader bool `json:"isTrader"` +} + +// StakingBalance defines model for StakingBalance. +type StakingBalance struct { + // Available The amount that is available to trade + Available *openapi_types.DecimalNumber `json:"available,omitempty"` + + // AvailableForWithdrawal The Staking amount that is available to redeem to exchange account + AvailableForWithdrawal *openapi_types.DecimalNumber `json:"availableForWithdrawal,omitempty"` + + // Balance The current Staking balance + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + BalanceByProvider *map[string]struct { + // Balance The current Staking balance per providerId + Balance *openapi_types.DecimalNumber `json:"balance,omitempty"` + } `json:"balanceByProvider,omitempty"` + + // Currency Currency code, see symbols and minimums + Currency *string `json:"currency,omitempty"` + + // Type Will always be "Staking" + Type *string `json:"type,omitempty"` +} + +// StakingDeposit defines model for StakingDeposit. +type StakingDeposit struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rates A JSON object including one or many rates. If more than one rate it would be an array of rates. + Rates *struct { + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *int `json:"rate,omitempty"` + } `json:"rates,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StakingHistory defines model for StakingHistory. +type StakingHistory struct { + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + Transactions *[]StakingTransaction `json:"transactions,omitempty"` +} + +// StakingRate defines model for StakingRate. +type StakingRate struct { + // ApyPct Staking interest APY (Expressed as a percentage derived from the rate and rounded to 1/10th of a percent.) + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // DepositUsdLimit Maximum new amount in USD notional of this crypto that can participate in Gemini Staking per account per month + DepositUsdLimit *int `json:"depositUsdLimit,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // Rate Staking interest rate in bps (Expressed as a simple rate. Interest on Staking balances compounds daily. In mobile and web applications, APYs are derived from this rate and rounded to 1/10th of a percent.) + Rate *openapi_types.DecimalNumber `json:"rate,omitempty"` + + // RatePct `rate` expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRateProvider Currency Symbol Keys +type StakingRateProvider struct { + CurrencySymbol *StakingRate `json:"currency_symbol,omitempty"` +} + +// StakingRateResponse Provider UUID Keys +type StakingRateResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRateProvider `json:"provider_uuid,omitempty"` +} + +// StakingRewardPeriod defines model for StakingRewardPeriod. +type StakingRewardPeriod struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // ApyPct Staking reward rate expressed as an APY at time of accrual. Interest on Staking balances compounds daily based on the simple rate which is available from `/v1/staking/rates/` + ApyPct *openapi_types.DecimalNumber `json:"apyPct,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // FirstAccrualAt Time of first accrual. In iso datetime with timezone format + FirstAccrualAt *string `json:"firstAccrualAt,omitempty"` + + // LastAccrualAt Time of last accrual. In iso datetime with timezone format + LastAccrualAt *string `json:"lastAccrualAt,omitempty"` + + // NumberOfAccruals Number of accruals in the specific aggregate, typically one per day. If the rate is adjusted, new accruals are added. + NumberOfAccruals *int `json:"numberOfAccruals,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePct Rate expressed as a percentage + RatePct *openapi_types.DecimalNumber `json:"ratePct,omitempty"` +} + +// StakingRewards defines model for StakingRewards. +type StakingRewards struct { + // AccrualTotal The total accrual + AccrualTotal *openapi_types.DecimalNumber `json:"accrualTotal,omitempty"` + + // Currency Currency code, see [symbols](/market-data/symbols-and-minimums) + Currency *string `json:"currency,omitempty"` + + // ProviderId Provider Id, in uuid4 format + ProviderId *string `json:"providerId,omitempty"` + + // RatePeriods Array of JSON objects with period accrual information + RatePeriods *[]StakingRewardPeriod `json:"ratePeriods,omitempty"` +} + +// StakingRewardsProvider Currency Symbol Keys +type StakingRewardsProvider struct { + CurrencySymbol *StakingRewards `json:"currency_symbol,omitempty"` +} + +// StakingRewardsResponse Provider UUID Keys +type StakingRewardsResponse struct { + // ProviderUuid Currency Symbol Keys + ProviderUuid *StakingRewardsProvider `json:"provider_uuid,omitempty"` +} + +// StakingTransaction defines model for StakingTransaction. +type StakingTransaction struct { + // Amount The amount that is defined by the transactionType above + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountCurrency Currency code + AmountCurrency *string `json:"amountCurrency,omitempty"` + + // DateTime timestamp + DateTime *TimestampType `json:"dateTime,omitempty"` + + // PriceAmount Current market price of the underlying token at the time of the reward + PriceAmount *openapi_types.DecimalNumber `json:"priceAmount,omitempty"` + + // PriceCurrency A supported three-letter fiat currency code, e.g. usd + PriceCurrency *string `json:"priceCurrency,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` + + // TransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment + TransactionType *StakingTransactionTransactionType `json:"transactionType,omitempty"` +} + +// StakingTransactionTransactionType Can be any one of the following - Deposit, Redeem, Interest, RedeemPayment, AdminRedeem, AdminCreditAdjustment, AdminDebitAdjustment +type StakingTransactionTransactionType string + +// StakingWithdrawal defines model for StakingWithdrawal. +type StakingWithdrawal struct { + // Amount The amount deposited + Amount *openapi_types.DecimalNumber `json:"amount,omitempty"` + + // AmountPaidSoFar The amount redeemed successfully + AmountPaidSoFar *openapi_types.DecimalNumber `json:"amountPaidSoFar,omitempty"` + + // AmountRemaining The amount pending to be redeemed + AmountRemaining *openapi_types.DecimalNumber `json:"amountRemaining,omitempty"` + + // Currency Currency code + Currency *string `json:"currency,omitempty"` + + // RequestInitiated In ISO datetime with timezone format + RequestInitiated *string `json:"requestInitiated,omitempty"` + + // TransactionId A unique identifier for the staking transaction + TransactionId *string `json:"transactionId,omitempty"` +} + +// StopLimitOrderResponse defines model for StopLimitOrderResponse. +type StopLimitOrderResponse struct { + AvgExecutionPrice *string `json:"avg_execution_price,omitempty"` + Exchange *string `json:"exchange,omitempty"` + ExecutedAmount *string `json:"executed_amount,omitempty"` + Id *string `json:"id,omitempty"` + IsCancelled *bool `json:"is_cancelled,omitempty"` + IsHidden *bool `json:"is_hidden,omitempty"` + IsLive *bool `json:"is_live,omitempty"` + Options *[]string `json:"options,omitempty"` + OrderId *string `json:"order_id,omitempty"` + OriginalAmount *string `json:"original_amount,omitempty"` + Price *string `json:"price,omitempty"` + Side *StopLimitOrderResponseSide `json:"side,omitempty"` + StopPrice *string `json:"stop_price,omitempty"` + Symbol *string `json:"symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + Type *StopLimitOrderResponseType `json:"type,omitempty"` + WasForced *bool `json:"was_forced,omitempty"` +} + +// StopLimitOrderResponseSide defines model for StopLimitOrderResponse.Side. +type StopLimitOrderResponseSide string + +// StopLimitOrderResponseType defines model for StopLimitOrderResponse.Type. +type StopLimitOrderResponseType string + +// SymbolDetails defines model for SymbolDetails. +type SymbolDetails struct { + // BaseCurrency CCY1 or the top currency. (i.e `BTC` in `BTCUSD`) + BaseCurrency *string `json:"base_currency,omitempty"` + + // ContractPriceCurrency CCY2 or the quote currency for spot instrument (i.e. `USD` in `BTCUSD`) + // Or collateral currency of the contract in case of perpetual swap instrument. + ContractPriceCurrency *string `json:"contract_price_currency,omitempty"` + + // ContractType `vanilla` / `linear` / `inverse` where `vanilla` is for spot + // while `linear` is for perpetual swap and `inverse` is a special case perpetual swap where the perpetual contract will be settled in base currency. + ContractType *string `json:"contract_type,omitempty"` + + // MinOrderSize The minimum order size in `base_currency` units (i.e `0.00001`) + MinOrderSize *string `json:"min_order_size,omitempty"` + + // ProductType Instrument type `spot` / `swap` -- where `swap` signifies `perpetual swap`. + ProductType *string `json:"product_type,omitempty"` + + // QuoteCurrency CCY2 or the quote currency. (i.e `USD` in `BTCUSD`) + QuoteCurrency *string `json:"quote_currency,omitempty"` + + // QuoteIncrement The number of decimal places in the `quote_currency` (i.e `0.01`) + QuoteIncrement *openapi_types.DecimalNumber `json:"quote_increment,omitempty"` + + // Status Status of the current order book. Can be `open`, `closed`, `cancel_only`, `post_only`, `limit_only`. + Status *string `json:"status,omitempty"` + + // Symbol The requested symbol. See [**symbols and minimums**](/market-data/symbols-and-minimums#all-supported-symbols) + Symbol *string `json:"symbol,omitempty"` + + // TickSize The number of decimal places in the `base_currency`. (i.e `1e-8`) + TickSize *openapi_types.DecimalNumber `json:"tick_size,omitempty"` + + // WrapEnabled When `True`, symbol can be wrapped using this endpoint: + // `POST https://api.gemini.com/v1/wrap/:symbol` + WrapEnabled *bool `json:"wrap_enabled,omitempty"` +} + +// Ticker defines model for Ticker. +type Ticker struct { + // Ask The lowest ask currently available + Ask *string `json:"ask,omitempty"` + + // Bid The highest bid currently available + Bid *string `json:"bid,omitempty"` + + // Last The price of the last executed trade + Last *string `json:"last,omitempty"` + + // Volume Information about the 24 hour volume on the exchange. See properties below + Volume *struct { + // PriceSymbol The volume denominated in the price currency + PriceSymbol *string `json:"price_symbol,omitempty"` + + // QuantitySymbol The volume denominated in the quantity currency + QuantitySymbol *string `json:"quantity_symbol,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + } `json:"volume,omitempty"` +} + +// TickerInfo defines model for TickerInfo. +type TickerInfo struct { + // Ask Current best offer + Ask *string `json:"ask,omitempty"` + + // Bid Current best bid + Bid *string `json:"bid,omitempty"` + + // Changes Hourly prices descending for past 24 hours + Changes *[]string `json:"changes,omitempty"` + + // Close Close price (most recent trade) + Close *string `json:"close,omitempty"` + + // High High price from 24 hours ago + High *string `json:"high,omitempty"` + + // Low Low price from 24 hours ago + Low *string `json:"low,omitempty"` + + // Open Open price from 24 hours ago + Open *string `json:"open,omitempty"` + + // Symbol The trading pair symbol + Symbol *string `json:"symbol,omitempty"` +} + +// TimestampType timestamp +type TimestampType struct { + union json.RawMessage +} + +// TimestampType0 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------|-----------------------|------------------------| +// | string (seconds) | `1495127793` | `POST` only | +// | string (milliseconds) | `1495127793000` | `POST` only | +type TimestampType0 = string + +// TimestampType1 Gemini strongly recommends using milliseconds instead of seconds for timestamps. +// +// | Timestamp format | Example | Supported request type | +// |-----------------------------|---------------------------|------------------------| +// | whole number (seconds) | `1495127793` | `GET`, `POST` | +// | whole number (milliseconds) | `1495127793000` | `GET`, `POST` | +type TimestampType1 = int64 + +// Trade defines model for Trade. +type Trade struct { + // Amount The amount that was traded + Amount *string `json:"amount,omitempty"` + + // Broken Whether the trade was broken or not. Broken trades will not be displayed by default; use the `include_breaks` to display them. + Broken *bool `json:"broken,omitempty"` + + // Exchange Will always be "gemini" + Exchange *string `json:"exchange,omitempty"` + + // Price The price the trade was executed at + Price *string `json:"price,omitempty"` + + // Tid The trade ID number + Tid *int64 `json:"tid,omitempty"` + + // Timestamp timestamp + Timestamp *TimestampType `json:"timestamp,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // Type - `buy` means that an ask was removed from the book by an incoming buy order. + // - `sell` means that a bid was removed from the book by an incoming sell order. + Type *TradeType `json:"type,omitempty"` +} + +// TradeType - `buy` means that an ask was removed from the book by an incoming buy order. +// - `sell` means that a bid was removed from the book by an incoming sell order. +type TradeType string + +// TradeVolume defines model for TradeVolume. +type TradeVolume struct { + BaseCurrency *string `json:"base_currency,omitempty"` + BuyMakerBase *string `json:"buy_maker_base,omitempty"` + BuyMakerCount *int `json:"buy_maker_count,omitempty"` + BuyMakerNotional *string `json:"buy_maker_notional,omitempty"` + BuyTakerBase *string `json:"buy_taker_base,omitempty"` + BuyTakerCount *int `json:"buy_taker_count,omitempty"` + BuyTakerNotional *string `json:"buy_taker_notional,omitempty"` + DataDate *string `json:"data_date,omitempty"` + MakerBuySellRatio *string `json:"maker_buy_sell_ratio,omitempty"` + NotionalCurrency *string `json:"notional_currency,omitempty"` + QuoteCurrency *string `json:"quote_currency,omitempty"` + SellMakerBase *string `json:"sell_maker_base,omitempty"` + SellMakerCount *int `json:"sell_maker_count,omitempty"` + SellMakerNotional *string `json:"sell_maker_notional,omitempty"` + SellTakerBase *string `json:"sell_taker_base,omitempty"` + SellTakerCount *int `json:"sell_taker_count,omitempty"` + SellTakerNotional *string `json:"sell_taker_notional,omitempty"` + Symbol *string `json:"symbol,omitempty"` + TotalVolumeBase *string `json:"total_volume_base,omitempty"` +} + +// Transaction defines model for Transaction. +type Transaction struct { + union json.RawMessage +} + +// Transaction0 Trade Reponse +type Transaction0 struct { + // Account The account. + Account *string `json:"account,omitempty"` + + // Amount The quantity that was executed. + Amount *string `json:"amount,omitempty"` + + // ClientOrderId The client order ID, if defined. Otherwise an empty string. + ClientOrderId *string `json:"clientOrderId,omitempty"` + + // Exchange Will always be "gemini". + Exchange *string `json:"exchange,omitempty"` + + // FeeAmount The fee amount charged + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeAssetCode The symbol that the trade was for + FeeAssetCode *string `json:"feeAssetCode,omitempty"` + + // IsAggressor If true, this order was the taker in the trade. + IsAggressor *bool `json:"isAggressor,omitempty"` + + // IsAuctionFill True if the trade was a auction trade and not an on-exchange trade. + IsAuctionFill *bool `json:"isAuctionFill,omitempty"` + + // IsClearingFill True if the trade was a clearing trade and not an on-exchange trade. + IsClearingFill *bool `json:"isClearingFill,omitempty"` + + // OrderId The order that this trade executed against. + OrderId *int64 `json:"orderId,omitempty"` + + // Price The price that the execution happened at. + Price *string `json:"price,omitempty"` + + // Side Indicating the side of the original order. + Side *string `json:"side,omitempty"` + + // Symbol The symbol that the trade was for. + Symbol *string `json:"symbol,omitempty"` + + // Tid The trade ID. + Tid *int64 `json:"tid,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` +} + +// Transaction1 Transfer Reponse +type Transaction1 struct { + // AdvanceEid Deposit advance event ID. + AdvanceEid *int64 `json:"advanceEid,omitempty"` + + // Amount The quantity that was transferred. + Amount *string `json:"amount,omitempty"` + + // BankId Bank ID. + BankId *string `json:"bankId,omitempty"` + + // ClientTransferId Client Transfer ID. Client transfer ID is an optional client-supplied unique identifier for each withdrawal or internal transfer. + ClientTransferId *string `json:"clientTransferId,omitempty"` + + // CorrelationId Correlation ID. + CorrelationId *int64 `json:"correlationId,omitempty"` + + // Currency Currency code, see symbols + Currency *string `json:"currency,omitempty"` + + // Destination The account you are transferring to. + Destination *string `json:"destination,omitempty"` + + // Eid Transfer event id. + Eid *int64 `json:"eid,omitempty"` + + // FeeId Fee ID. + FeeId *string `json:"feeId,omitempty"` + + // Method Type of transfer method. + Method *string `json:"method,omitempty"` + + // OperationReason The operation reason. + OperationReason *string `json:"operationReason,omitempty"` + + // PendingEid Pending event ID. + PendingEid *int64 `json:"pendingEid,omitempty"` + + // Purpose Purpose. + Purpose *string `json:"purpose,omitempty"` + + // Source The account you are transferring from. + Source *string `json:"source,omitempty"` + + // Status The status of the transfer. + Status *string `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TransactionHash Supplies the transaction hash when available. + TransactionHash *string `json:"transactionHash,omitempty"` + + // TransferId Transfer ID. + TransferId *string `json:"transferId,omitempty"` + + // TransferType Transfer type. + TransferType *string `json:"transferType,omitempty"` + + // WithdrawalEid Withdrawal event ID. + WithdrawalEid *int64 `json:"withdrawalEid,omitempty"` + + // WithdrawalId Withdrawal ID. + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// Transfer defines model for Transfer. +type Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Eid The transfer ID + Eid *int64 `json:"eid,omitempty"` + Status *TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The transaction hash if applicable + TxHash *string `json:"txHash,omitempty"` + Type *TransferType `json:"type,omitempty"` +} + +// TransferStatus defines model for Transfer.Status. +type TransferStatus string + +// TransferType defines model for Transfer.Type. +type TransferType string + +// V2Transfer defines model for V2Transfer. +type V2Transfer struct { + // Amount The amount transferred + Amount *string `json:"amount,omitempty"` + + // Currency The currency transferred + Currency *string `json:"currency,omitempty"` + + // Destination The destination address for withdrawals + Destination *string `json:"destination,omitempty"` + + // Eid The transfer event ID + Eid *int64 `json:"eid,omitempty"` + + // FeeAmount The fee charged for the transfer + FeeAmount *string `json:"feeAmount,omitempty"` + + // FeeCurrency The currency in which the fee was charged + FeeCurrency *string `json:"feeCurrency,omitempty"` + + // Method The transfer method (e.g., `ACH`, `CreditCard`) + Method *string `json:"method,omitempty"` + + // Network The blockchain network the transfer was executed on (e.g., `ethereum`, `solana`, `arbitrum`, `optimism`, `base`, `avalanche`). Not present for fiat or administrative transfers. + Network *string `json:"network,omitempty"` + + // OutputIdx The output index for withdrawals + OutputIdx *int `json:"outputIdx,omitempty"` + + // Purpose The purpose or reason for administrative transfers + Purpose *string `json:"purpose,omitempty"` + + // Status The status of the transfer + Status *V2TransferStatus `json:"status,omitempty"` + + // Timestampms timestamp + Timestampms *TimestampType `json:"timestampms,omitempty"` + + // TxHash The on-chain transaction hash, if applicable + TxHash *string `json:"txHash,omitempty"` + + // Type The type of the transfer + Type *V2TransferType `json:"type,omitempty"` + + // WithdrawalId The unique withdrawal identifier + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// V2TransferStatus The status of the transfer +type V2TransferStatus string + +// V2TransferType The type of the transfer +type V2TransferType string + +// WithdrawCryptoFundsResponse Response returned after submitting a v2 cryptocurrency withdrawal. +type WithdrawCryptoFundsResponse struct { + // Address Standard string format of the withdrawal destination address + Address *string `json:"address,omitempty"` + + // Amount The withdrawal amount + Amount *string `json:"amount,omitempty"` + + // Currency The currency code of the withdrawn asset + Currency *string `json:"currency,omitempty"` + + // Fee The fee charged for the withdrawal + Fee *string `json:"fee,omitempty"` + + // WithdrawalId A unique ID for the withdrawal + WithdrawalId *string `json:"withdrawalId,omitempty"` +} + +// ApiKeyAuth defines model for apiKeyAuth. +type ApiKeyAuth = string + +// CacheControl defines model for cacheControl. +type CacheControl = string + +// ContentLength defines model for contentLength. +type ContentLength = string + +// ContentType defines model for contentType. +type ContentType = string + +// CurrencyParam defines model for currencyParam. +type CurrencyParam = string + +// NetworkParam defines model for networkParam. +type NetworkParam = string + +// PayloadAuth defines model for payloadAuth. +type PayloadAuth = string + +// SignatureAuth defines model for signatureAuth. +type SignatureAuth = string + +// SymbolParam defines model for symbolParam. +type SymbolParam = string + +// TimestampParam timestamp +type TimestampParam = TimestampType + +// ApiKeyIpFilteringFailure defines model for ApiKeyIpFilteringFailure. +type ApiKeyIpFilteringFailure = ErrorResponse + +// BadRequest defines model for BadRequest. +type BadRequest = ErrorResponse + +// InternalError defines model for InternalError. +type InternalError = ErrorResponse + +// NotFound defines model for NotFound. +type NotFound = ErrorResponse + +// TooManyRequests defines model for TooManyRequests. +type TooManyRequests = ErrorResponse + +// Unauthorized defines model for Unauthorized. +type Unauthorized = ErrorResponse + +// apiKeyAuthContextKey is the context key for apiKeyAuth security scheme +type apiKeyAuthContextKey string + +// payloadAuthContextKey is the context key for payloadAuth security scheme +type payloadAuthContextKey string + +// signatureAuthContextKey is the context key for signatureAuth security scheme +type signatureAuthContextKey string + +// SendHeartbeatParams defines parameters for SendHeartbeat. +type SendHeartbeatParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListPastTradesParams defines parameters for ListPastTrades. +type ListPastTradesParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetNotionalTradingVolumeJSONBody defines parameters for GetNotionalTradingVolume. +type GetNotionalTradingVolumeJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// GetNotionalTradingVolumeParams defines parameters for GetNotionalTradingVolume. +type GetNotionalTradingVolumeParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CancelOrderParams defines parameters for CancelOrder. +type CancelOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CancelAllActiveOrdersParams defines parameters for CancelAllActiveOrders. +type CancelAllActiveOrdersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CancelAllSessionOrdersParams defines parameters for CancelAllSessionOrders. +type CancelAllSessionOrdersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CreateNewOrderParams defines parameters for CreateNewOrder. +type CreateNewOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// CreateNewOrder200JSONResponseBody defines parameters for CreateNewOrder. +type CreateNewOrder200JSONResponseBody struct { + union json.RawMessage +} + +// GetOrderStatusParams defines parameters for GetOrderStatus. +type GetOrderStatusParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListActiveOrdersJSONBody defines parameters for ListActiveOrders. +type ListActiveOrdersJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// ListActiveOrdersParams defines parameters for ListActiveOrders. +type ListActiveOrdersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// ListPastOrdersJSONBody defines parameters for ListPastOrders. +type ListPastOrdersJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // LimitOrders The maximum number of orders to return. Default is 50, max is 500. + LimitOrders *int `json:"limit_orders,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The API endpoint `/v1/orders/history` + Request string `json:"request"` + + // Symbol The symbol to retrieve orders for + Symbol *string `json:"symbol,omitempty"` + + // Timestamp In iso datetime with timezone format from that date you will get order history + Timestamp *TimestampType `json:"timestamp,omitempty"` +} + +// ListPastOrdersParams defines parameters for ListPastOrders. +type ListPastOrdersParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// GetTradingVolumeJSONBody defines parameters for GetTradingVolume. +type GetTradingVolumeJSONBody struct { + // Account Required for Master API keys as described in [Private API Invocation](/authentication/api-key#private-api-invocation). The name of the account within the subaccount group. Specifies the account on which you intend to place the order. Only available for exchange accounts. + Account *string `json:"account,omitempty"` + + // Nonce timestamp + Nonce TimestampType `json:"nonce"` + + // Request The API endpoint path + Request string `json:"request"` +} + +// GetTradingVolumeParams defines parameters for GetTradingVolume. +type GetTradingVolumeParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// WrapOrderJSONBody defines parameters for WrapOrder. +type WrapOrderJSONBody struct { + // Account Required for Master API keys. The name of the account within the subaccount group. + Account *string `json:"account,omitempty"` + + // Amount The amount to wrap + Amount string `json:"amount"` + + // ClientOrderId A client-specified order id + ClientOrderId *string `json:"client_order_id,omitempty"` + + // Nonce The nonce, as described in [Private API Invocation](/authentication/api-key#private-api-invocation) + Nonce Nonce `json:"nonce"` + + // Request The literal string "/v1/wrap/symbol" + Request string `json:"request"` + + // Side "buy" or "sell" + Side *WrapOrderJSONBodySide `json:"side,omitempty"` +} + +// WrapOrderParams defines parameters for WrapOrder. +type WrapOrderParams struct { + // XGEMINIAPIKEY Your API key + XGEMINIAPIKEY ApiKeyAuth `json:"X-GEMINI-APIKEY"` + + // XGEMINISIGNATURE HEX-encoded HMAC-SHA384 of payload signed with API secret + XGEMINISIGNATURE SignatureAuth `json:"X-GEMINI-SIGNATURE"` + + // XGEMINIPAYLOAD Base64-encoded JSON payload + XGEMINIPAYLOAD PayloadAuth `json:"X-GEMINI-PAYLOAD"` + ContentType *ContentType `json:"Content-Type,omitempty"` + ContentLength *ContentLength `json:"Content-Length,omitempty"` + CacheControl *CacheControl `json:"Cache-Control,omitempty"` +} + +// WrapOrderJSONBodySide defines parameters for WrapOrder. +type WrapOrderJSONBodySide string + +// SendHeartbeatJSONRequestBody defines body for SendHeartbeat for application/json ContentType. +type SendHeartbeatJSONRequestBody = Heartbeat + +// ListPastTradesJSONRequestBody defines body for ListPastTrades for application/json ContentType. +type ListPastTradesJSONRequestBody = MyTradesRequest + +// GetNotionalTradingVolumeJSONRequestBody defines body for GetNotionalTradingVolume for application/json ContentType. +type GetNotionalTradingVolumeJSONRequestBody GetNotionalTradingVolumeJSONBody + +// CancelOrderJSONRequestBody defines body for CancelOrder for application/json ContentType. +type CancelOrderJSONRequestBody = CancelOrderRequest + +// CancelAllActiveOrdersJSONRequestBody defines body for CancelAllActiveOrders for application/json ContentType. +type CancelAllActiveOrdersJSONRequestBody = CancelAllOrdersRequest + +// CancelAllSessionOrdersJSONRequestBody defines body for CancelAllSessionOrders for application/json ContentType. +type CancelAllSessionOrdersJSONRequestBody = CancelAllOrdersBySessionRequest + +// CreateNewOrderJSONRequestBody defines body for CreateNewOrder for application/json ContentType. +type CreateNewOrderJSONRequestBody = NewOrderRequest + +// GetOrderStatusJSONRequestBody defines body for GetOrderStatus for application/json ContentType. +type GetOrderStatusJSONRequestBody = OrderStatusRequest + +// ListActiveOrdersJSONRequestBody defines body for ListActiveOrders for application/json ContentType. +type ListActiveOrdersJSONRequestBody ListActiveOrdersJSONBody + +// ListPastOrdersJSONRequestBody defines body for ListPastOrders for application/json ContentType. +type ListPastOrdersJSONRequestBody ListPastOrdersJSONBody + +// GetTradingVolumeJSONRequestBody defines body for GetTradingVolume for application/json ContentType. +type GetTradingVolumeJSONRequestBody GetTradingVolumeJSONBody + +// WrapOrderJSONRequestBody defines body for WrapOrder for application/json ContentType. +type WrapOrderJSONRequestBody WrapOrderJSONBody + +// AsHeartbeatNonce0 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce0 +func (t Heartbeat_Nonce) AsHeartbeatNonce0() (HeartbeatNonce0, error) { + var body HeartbeatNonce0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce0 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) FromHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce0 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce0 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce0(v HeartbeatNonce0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsHeartbeatNonce1 returns the union data inside the Heartbeat_Nonce as a HeartbeatNonce1 +func (t Heartbeat_Nonce) AsHeartbeatNonce1() (HeartbeatNonce1, error) { + var body HeartbeatNonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHeartbeatNonce1 overwrites any union data inside the Heartbeat_Nonce as the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) FromHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHeartbeatNonce1 performs a merge with any union data inside the Heartbeat_Nonce, using the provided HeartbeatNonce1 +func (t *Heartbeat_Nonce) MergeHeartbeatNonce1(v HeartbeatNonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Heartbeat_Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Heartbeat_Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType returns the union data inside the Nonce as a TimestampType +func (t Nonce) AsTimestampType() (TimestampType, error) { + var body TimestampType + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType overwrites any union data inside the Nonce as the provided TimestampType +func (t *Nonce) FromTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType performs a merge with any union data inside the Nonce, using the provided TimestampType +func (t *Nonce) MergeTimestampType(v TimestampType) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNonce1 returns the union data inside the Nonce as a Nonce1 +func (t Nonce) AsNonce1() (Nonce1, error) { + var body Nonce1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNonce1 overwrites any union data inside the Nonce as the provided Nonce1 +func (t *Nonce) FromNonce1(v Nonce1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNonce1 performs a merge with any union data inside the Nonce, using the provided Nonce1 +func (t *Nonce) MergeNonce1(v Nonce1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Nonce) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Nonce) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTimestampType0 returns the union data inside the TimestampType as a TimestampType0 +func (t TimestampType) AsTimestampType0() (TimestampType0, error) { + var body TimestampType0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType0 overwrites any union data inside the TimestampType as the provided TimestampType0 +func (t *TimestampType) FromTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType0 performs a merge with any union data inside the TimestampType, using the provided TimestampType0 +func (t *TimestampType) MergeTimestampType0(v TimestampType0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTimestampType1 returns the union data inside the TimestampType as a TimestampType1 +func (t TimestampType) AsTimestampType1() (TimestampType1, error) { + var body TimestampType1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTimestampType1 overwrites any union data inside the TimestampType as the provided TimestampType1 +func (t *TimestampType) FromTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTimestampType1 performs a merge with any union data inside the TimestampType, using the provided TimestampType1 +func (t *TimestampType) MergeTimestampType1(v TimestampType1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t TimestampType) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *TimestampType) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsTransaction0 returns the union data inside the Transaction as a Transaction0 +func (t Transaction) AsTransaction0() (Transaction0, error) { + var body Transaction0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction0 overwrites any union data inside the Transaction as the provided Transaction0 +func (t *Transaction) FromTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction0 performs a merge with any union data inside the Transaction, using the provided Transaction0 +func (t *Transaction) MergeTransaction0(v Transaction0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTransaction1 returns the union data inside the Transaction as a Transaction1 +func (t Transaction) AsTransaction1() (Transaction1, error) { + var body Transaction1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTransaction1 overwrites any union data inside the Transaction as the provided Transaction1 +func (t *Transaction) FromTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTransaction1 performs a merge with any union data inside the Transaction, using the provided Transaction1 +func (t *Transaction) MergeTransaction1(v Transaction1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t Transaction) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *Transaction) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsLimitOrderResponse returns the union data inside the CreateNewOrder200JSONResponseBody as a LimitOrderResponse +func (t CreateNewOrder200JSONResponseBody) AsLimitOrderResponse() (LimitOrderResponse, error) { + var body LimitOrderResponse + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromLimitOrderResponse overwrites any union data inside the CreateNewOrder200JSONResponseBody as the provided LimitOrderResponse +func (t *CreateNewOrder200JSONResponseBody) FromLimitOrderResponse(v LimitOrderResponse) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeLimitOrderResponse performs a merge with any union data inside the CreateNewOrder200JSONResponseBody, using the provided LimitOrderResponse +func (t *CreateNewOrder200JSONResponseBody) MergeLimitOrderResponse(v LimitOrderResponse) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsStopLimitOrderResponse returns the union data inside the CreateNewOrder200JSONResponseBody as a StopLimitOrderResponse +func (t CreateNewOrder200JSONResponseBody) AsStopLimitOrderResponse() (StopLimitOrderResponse, error) { + var body StopLimitOrderResponse + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromStopLimitOrderResponse overwrites any union data inside the CreateNewOrder200JSONResponseBody as the provided StopLimitOrderResponse +func (t *CreateNewOrder200JSONResponseBody) FromStopLimitOrderResponse(v StopLimitOrderResponse) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeStopLimitOrderResponse performs a merge with any union data inside the CreateNewOrder200JSONResponseBody, using the provided StopLimitOrderResponse +func (t *CreateNewOrder200JSONResponseBody) MergeStopLimitOrderResponse(v StopLimitOrderResponse) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t CreateNewOrder200JSONResponseBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *CreateNewOrder200JSONResponseBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/packages/sdk-go/go.mod b/packages/sdk-go/go.mod new file mode 100644 index 0000000..546f677 --- /dev/null +++ b/packages/sdk-go/go.mod @@ -0,0 +1,3 @@ +module github.com/gemini/developer-platform/packages/sdk-go + +go 1.23 diff --git a/packages/sdk-go/internal/runtime/union.go b/packages/sdk-go/internal/runtime/union.go new file mode 100644 index 0000000..4484458 --- /dev/null +++ b/packages/sdk-go/internal/runtime/union.go @@ -0,0 +1,55 @@ +package runtime + +import ( + "bytes" + "encoding/json" + "fmt" + "io" +) + +// JSONMerge merges JSON object b on top of JSON object a. +func JSONMerge(a []byte, b []byte) ([]byte, error) { + if len(a) == 0 || bytes.Equal(a, []byte("null")) { + return b, nil + } + if len(b) == 0 || bytes.Equal(b, []byte("null")) { + return a, nil + } + left, err := decodeJSONValue(a) + if err != nil { + return nil, err + } + right, err := decodeJSONValue(b) + if err != nil { + return nil, err + } + leftMap, leftOK := left.(map[string]any) + rightMap, rightOK := right.(map[string]any) + if !leftOK || !rightOK { + // Union branches are occasionally scalar values. The later branch still + // has precedence, just as object members from b do. + return b, nil + } + for k, v := range rightMap { + leftMap[k] = v + } + return json.Marshal(leftMap) +} + +func decodeJSONValue(value []byte) (any, error) { + decoder := json.NewDecoder(bytes.NewReader(value)) + decoder.UseNumber() + + var decoded any + if err := decoder.Decode(&decoded); err != nil { + return nil, err + } + var extra any + if err := decoder.Decode(&extra); err != io.EOF { + if err == nil { + return nil, fmt.Errorf("json merge: multiple JSON values") + } + return nil, err + } + return decoded, nil +} diff --git a/packages/sdk-go/internal/runtime/union_test.go b/packages/sdk-go/internal/runtime/union_test.go new file mode 100644 index 0000000..7e7515f --- /dev/null +++ b/packages/sdk-go/internal/runtime/union_test.go @@ -0,0 +1,32 @@ +package runtime + +import ( + "encoding/json" + "testing" +) + +func TestJSONMergePreservesLargeNumbers(t *testing.T) { + merged, err := JSONMerge( + []byte(`{"nonce":9007199254740993,"nested":{"value":1}}`), + []byte(`{"nested":{"value":9007199254740995}}`), + ) + if err != nil { + t.Fatalf("JSONMerge returned error: %v", err) + } + var fields map[string]json.RawMessage + if err := json.Unmarshal(merged, &fields); err != nil { + t.Fatalf("merged JSON is invalid: %v", err) + } + if string(fields["nonce"]) != "9007199254740993" { + t.Fatalf("JSONMerge changed nonce precision: %s", fields["nonce"]) + } + if string(fields["nested"]) != `{"value":9007199254740995}` { + t.Fatalf("JSONMerge changed nested precision: %s", fields["nested"]) + } +} + +func TestJSONMergeRejectsMultipleValues(t *testing.T) { + if _, err := JSONMerge([]byte(`{} {}`), []byte(`{}`)); err == nil { + t.Fatal("expected multiple JSON values to be rejected") + } +} diff --git a/packages/sdk-go/memory_leak_test.go b/packages/sdk-go/memory_leak_test.go new file mode 100644 index 0000000..40a9608 --- /dev/null +++ b/packages/sdk-go/memory_leak_test.go @@ -0,0 +1,145 @@ +package gemini_test + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "os" + "runtime" + "runtime/pprof" + "testing" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go" + "github.com/gemini/developer-platform/packages/sdk-go/types" + "github.com/gemini/developer-platform/packages/sdk-go/websocket" + "github.com/gemini/developer-platform/packages/sdk-go/websocket/orderbook" +) + +type mockDialer struct{} +type mockConn struct { + closed chan struct{} + responses chan []byte +} + +func (m *mockDialer) Dial(ctx context.Context, urlStr string, requestHeader http.Header) (websocket.Conn, *http.Response, error) { + return &mockConn{ + closed: make(chan struct{}), + responses: make(chan []byte, 4), + }, &http.Response{StatusCode: 101}, nil +} + +func (m *mockConn) ReadMessage(ctx context.Context) (int, []byte, error) { + select { + case <-m.closed: + return 0, nil, context.Canceled + case <-ctx.Done(): + return 0, nil, ctx.Err() + case response := <-m.responses: + return websocket.TextMessage, response, nil + } +} + +func (m *mockConn) WriteMessage(ctx context.Context, messageType int, data []byte) error { + var request struct { + ID int64 `json:"id"` + Method string `json:"method"` + } + if err := json.Unmarshal(data, &request); err != nil || request.ID == 0 || request.Method == "" { + return nil + } + response, err := json.Marshal(map[string]any{ + "id": request.ID, + "status": http.StatusOK, + "result": map[string]any{}, + }) + if err != nil { + return err + } + select { + case <-ctx.Done(): + return ctx.Err() + case <-m.closed: + return context.Canceled + case m.responses <- response: + return nil + } +} + +func (m *mockConn) Close() error { + select { + case <-m.closed: + default: + close(m.closed) + } + return nil +} + +func TestZeroGoroutineAndMemoryLeak(t *testing.T) { + server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"result":"ok"}`)) + })) + defer server.Close() + httpClient := server.Client() + defer httpClient.CloseIdleConnections() + + // Baseline goroutine count + runtime.GC() + time.Sleep(50 * time.Millisecond) + initialGoroutines := runtime.NumGoroutine() + + for cycle := 0; cycle < 50; cycle++ { + // 1. WebSocket Client Lifecycle + ws := websocket.NewClient("wss://api.gemini.com/v1/marketdata", + websocket.WithDialer(&mockDialer{}), + websocket.WithAutoReconnect(false), + ) + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + _ = ws.Connect(ctx) + subChan, _ := ws.SubscribeDepth(ctx, "BTCUSD") + cancel() + + _ = ws.Send(context.Background(), map[string]string{"type": "subscribe"}) + + // 2. OrderBook Ingestion & Memory Allocation + book := orderbook.NewOrderBook("BTCUSD") + for i := 0; i < 100; i++ { + book.ApplySnapshot(int64(i), [][]string{{"60000", "1.0"}}, [][]string{{"60100", "1.0"}}) + _, _ = book.VWAP(true, types.MustParseDecimal("0.5")) + _, _ = book.Imbalance(5) + } + + // 3. Heartbeat Session Lifecycle with mock server + hbClient := gemini.NewClient( + gemini.WithAPIKey("test-key", "test-secret"), + gemini.WithCustomRESTURL(server.URL), + gemini.WithHTTPClient(httpClient), + ) + session := hbClient.Heartbeat.Start(context.Background(), 20*time.Millisecond) + time.Sleep(5 * time.Millisecond) + session.Stop() + _ = hbClient.Close() + httpClient.CloseIdleConnections() + + // 4. Close WebSocket + _ = ws.Close() + + // Drain subChan + for range subChan { + } + } + + runtime.GC() + time.Sleep(100 * time.Millisecond) + finalGoroutines := runtime.NumGoroutine() + + if finalGoroutines > initialGoroutines+1 { + _ = pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) + t.Fatalf("Goroutine leak detected: started with %d, ended with %d", initialGoroutines, finalGoroutines) + } + + t.Logf("Memory test passed: 50 full cycles completed with 0 leaked goroutines (initial: %d, final: %d)", initialGoroutines, finalGoroutines) +} diff --git a/packages/sdk-go/oauth/oauth.go b/packages/sdk-go/oauth/oauth.go new file mode 100644 index 0000000..a544dc1 --- /dev/null +++ b/packages/sdk-go/oauth/oauth.go @@ -0,0 +1,893 @@ +// Package oauth provides OAuth 2.0 authorization-code and PKCE helpers for +// applications using the Gemini Go SDK. +// +// The package keeps interactive authorization optional. Applications can use +// Config.AuthCodeURL and Config.Exchange in their own browser flow, or use +// Config.Login for a loopback callback on localhost. TokenSource converts the +// resulting token into auth.TokenSource for REST requests and WebSocket +// connections. +package oauth + +import ( + "context" + "crypto/rand" + "crypto/sha256" + "crypto/subtle" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "html/template" + "io" + "log/slog" + "net" + "net/http" + "net/url" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/gemini/developer-platform/packages/sdk-go/auth" +) + +const ( + defaultEarlyExpiry = 30 * time.Second + defaultTokenTimeout = 15 * time.Second + maxTokenResponseBytes = 64 << 10 +) + +var ( + // ErrInvalidConfig indicates that the OAuth client configuration is not + // safe or complete enough to use. + ErrInvalidConfig = errors.New("gemini oauth: invalid configuration") + // ErrInvalidRedirectURL indicates that a redirect URL is malformed or is + // not a permitted HTTPS or loopback callback URL. + ErrInvalidRedirectURL = errors.New("gemini oauth: invalid redirect URL") + // ErrInvalidPKCE indicates that a PKCE verifier or state value is invalid. + ErrInvalidPKCE = errors.New("gemini oauth: invalid PKCE parameters") + // ErrStateMismatch indicates that the authorization callback did not match + // the state generated for the authorization attempt. + ErrStateMismatch = errors.New("gemini oauth: authorization state mismatch") + // ErrBrowserOpenerRequired indicates that Login was called without a + // browser opener. + ErrBrowserOpenerRequired = errors.New("gemini oauth: browser opener is required") + // ErrRedirectNotAllowed indicates that an OAuth token request attempted to + // follow an HTTP redirect. Token requests are never redirected. + ErrRedirectNotAllowed = errors.New("gemini oauth: token endpoint redirects are not allowed") + // ErrInvalidToken indicates that an OAuth token response or source token is + // missing required data. + ErrInvalidToken = errors.New("gemini oauth: invalid token") + // ErrRefreshTokenUnavailable indicates that an expired token has no refresh + // token available. + ErrRefreshTokenUnavailable = errors.New("gemini oauth: refresh token unavailable") + // ErrTokenRefresh identifies a failed refresh operation. + ErrTokenRefresh = errors.New("gemini oauth: token refresh failed") + // ErrTokenEndpoint indicates that an OAuth token endpoint rejected a + // request. + ErrTokenEndpoint = errors.New("gemini oauth: token endpoint rejected request") +) + +var callbackResponseTemplate = template.Must(template.New("oauth-callback-response").Parse("{{.}}")) + +// Endpoint contains the OAuth authorization and token endpoint URLs. +// Both endpoints must use HTTPS. +type Endpoint struct { + AuthURL string + TokenURL string +} + +// Config configures an OAuth authorization-code flow. +// +// ClientSecret is optional for public PKCE clients. HTTP requests to the +// token endpoint never follow redirects and use a bounded response body. +// HTTPClient is used only for token requests; when nil, the package uses a +// client with a finite timeout. +type Config struct { + ClientID string + ClientSecret string + Endpoint Endpoint + RedirectURL string + Scopes []string + HTTPClient *http.Client +} + +// String returns a diagnostic representation without exposing ClientSecret. +// Config values are commonly printed while diagnosing OAuth startup failures, +// so the safe representation is the default for ordinary fmt formatting. +func (c Config) String() string { + return fmt.Sprintf( + "oauth.Config{ClientID:%q, ClientSecret:%s, Endpoint:{AuthURL:%q, TokenURL:%q}, RedirectURL:%q, Scopes:%q, HTTPClientConfigured:%t}", + c.ClientID, secretPresence(c.ClientSecret), c.Endpoint.AuthURL, c.Endpoint.TokenURL, + c.RedirectURL, strings.Join(c.Scopes, ","), c.HTTPClient != nil, + ) +} + +// GoString returns a safe representation for %#v formatting. +func (c Config) GoString() string { + return c.String() +} + +// LogValue prevents structured loggers from reflecting ClientSecret or a +// caller-provided HTTP client's internal fields. +func (c Config) LogValue() slog.Value { + return slog.GroupValue( + slog.String("client_id", c.ClientID), + slog.Bool("client_secret_present", strings.TrimSpace(c.ClientSecret) != ""), + slog.String("authorization_endpoint", c.Endpoint.AuthURL), + slog.String("token_endpoint", c.Endpoint.TokenURL), + slog.String("redirect_url", c.RedirectURL), + slog.Any("scopes", append([]string(nil), c.Scopes...)), + slog.Bool("http_client_configured", c.HTTPClient != nil), + ) +} + +// Token is an OAuth access token and its optional refresh metadata. +type Token struct { + AccessToken string + RefreshToken string + TokenType string + ExpiresAt time.Time + Scope string +} + +// String returns a diagnostic representation without exposing access or +// refresh token material. OAuth tokens are routinely included in startup and +// refresh logs, so the safe representation is the default even with fmt's +// ordinary formatting verbs. +func (t Token) String() string { + return fmt.Sprintf( + "oauth.Token{AccessToken:%s, RefreshToken:%s, TokenType:%q, ExpiresAt:%s, Scope:%q}", + secretPresence(t.AccessToken), secretPresence(t.RefreshToken), t.TokenType, + t.ExpiresAt.UTC().Format(time.RFC3339), t.Scope, + ) +} + +// GoString returns a safe representation for %#v formatting. +func (t Token) GoString() string { + return t.String() +} + +// LogValue prevents structured loggers from reflecting the exported token +// fields and accidentally recording credentials. +func (t Token) LogValue() slog.Value { + return slog.GroupValue( + slog.Bool("access_token_present", strings.TrimSpace(t.AccessToken) != ""), + slog.Bool("refresh_token_present", strings.TrimSpace(t.RefreshToken) != ""), + slog.String("token_type", t.TokenType), + slog.Time("expires_at", t.ExpiresAt), + slog.String("scope", t.Scope), + ) +} + +func secretPresence(value string) string { + if strings.TrimSpace(value) == "" { + return "" + } + return "" +} + +// Valid reports whether the access token is present and remains valid after +// applying earlyExpiry. A zero ExpiresAt means the authorization server did +// not provide an expiry and the token is treated as valid until rejected. +func (t Token) Valid(now time.Time, earlyExpiry time.Duration) bool { + if strings.TrimSpace(t.AccessToken) == "" { + return false + } + return t.ExpiresAt.IsZero() || now.Add(earlyExpiry).Before(t.ExpiresAt) +} + +// GeneratePKCE returns a fresh RFC 7636 verifier and its S256 challenge. +func GeneratePKCE() (verifier string, challenge string, err error) { + raw := make([]byte, 32) + if _, err := rand.Read(raw); err != nil { + return "", "", fmt.Errorf("generate PKCE verifier: %w", err) + } + verifier = base64.RawURLEncoding.EncodeToString(raw) + challenge = pkceChallenge(verifier) + return verifier, challenge, nil +} + +// GenerateState returns a fresh state value suitable for CSRF protection. +func GenerateState() (string, error) { + raw := make([]byte, 32) + if _, err := rand.Read(raw); err != nil { + return "", fmt.Errorf("generate OAuth state: %w", err) + } + return base64.RawURLEncoding.EncodeToString(raw), nil +} + +// AuthCodeURL builds a PKCE authorization URL. The verifier is never placed +// in the URL; only its S256 challenge is sent to the authorization server. +func (c Config) AuthCodeURL(state, verifier string) (string, error) { + if err := c.validate(); err != nil { + return "", err + } + if err := validateState(state); err != nil { + return "", err + } + if err := validateVerifier(verifier); err != nil { + return "", err + } + + authURL, err := url.Parse(c.Endpoint.AuthURL) + if err != nil { + return "", fmt.Errorf("parse authorization endpoint: %w", err) + } + params := authURL.Query() + params.Set("client_id", c.ClientID) + params.Set("response_type", "code") + params.Set("redirect_uri", c.RedirectURL) + params.Set("state", state) + params.Set("code_challenge", pkceChallenge(verifier)) + params.Set("code_challenge_method", "S256") + if scope := normalizedScopes(c.Scopes); scope != "" { + params.Set("scope", scope) + } + authURL.RawQuery = params.Encode() + return authURL.String(), nil +} + +// Exchange exchanges a one-time authorization code for an access token. +func (c Config) Exchange(ctx context.Context, code, verifier string) (*Token, error) { + if err := c.validate(); err != nil { + return nil, err + } + if strings.TrimSpace(code) == "" { + return nil, fmt.Errorf("%w: authorization code is required", ErrInvalidPKCE) + } + if err := validateVerifier(verifier); err != nil { + return nil, err + } + form := url.Values{ + "grant_type": {"authorization_code"}, + "client_id": {c.ClientID}, + "code": {code}, + "redirect_uri": {c.RedirectURL}, + "code_verifier": {verifier}, + } + if c.ClientSecret != "" { + form.Set("client_secret", c.ClientSecret) + } + return c.tokenRequest(ctx, form) +} + +// Refresh exchanges a refresh token for a new access token. +func (c Config) Refresh(ctx context.Context, refreshToken string) (*Token, error) { + if err := c.validateTokenRequest(); err != nil { + return nil, err + } + if strings.TrimSpace(refreshToken) == "" { + return nil, ErrRefreshTokenUnavailable + } + form := url.Values{ + "grant_type": {"refresh_token"}, + "client_id": {c.ClientID}, + "refresh_token": {refreshToken}, + } + if c.ClientSecret != "" { + form.Set("client_secret", c.ClientSecret) + } + return c.tokenRequest(ctx, form) +} + +// BrowserOpener opens an authorization URL in a user agent. +type BrowserOpener func(string) error + +// Authorize runs an authorization-code flow using a caller-supplied consent +// handler. The handler must return the code and the state received from the +// provider callback. This is useful for web applications and custom CLI UIs. +func (c Config) Authorize(ctx context.Context, handler func(context.Context, string) (code, state string, err error)) (*Token, error) { + if handler == nil { + return nil, ErrBrowserOpenerRequired + } + if err := c.validate(); err != nil { + return nil, err + } + if ctx == nil { + ctx = context.Background() + } + verifier, _, err := GeneratePKCE() + if err != nil { + return nil, err + } + state, err := GenerateState() + if err != nil { + return nil, err + } + authURL, err := c.AuthCodeURL(state, verifier) + if err != nil { + return nil, err + } + code, returnedState, err := handler(ctx, authURL) + if err != nil { + return nil, err + } + if !secureStringEqual(state, returnedState) { + return nil, ErrStateMismatch + } + return c.Exchange(ctx, code, verifier) +} + +// Login runs an interactive PKCE flow using a loopback callback. The +// configured RedirectURL must be an exact localhost/loopback URL with a fixed +// port, such as http://localhost:8787/callback. HTTP is permitted only for +// this loopback callback; authorization and token endpoints must be HTTPS. +func (c Config) Login(ctx context.Context, openBrowser BrowserOpener) (*Token, error) { + if openBrowser == nil { + return nil, ErrBrowserOpenerRequired + } + if err := validateLoopbackRedirect(c.RedirectURL); err != nil { + return nil, err + } + + return c.Authorize(ctx, func(ctx context.Context, authURL string) (string, string, error) { + return c.loopbackCallback(ctx, authURL, openBrowser) + }) +} + +// Source is a concurrent-safe auth.TokenSource backed by an access token and +// its refresh token. Concurrent callers share one refresh operation, while a +// caller waiting for another refresh can still cancel its own wait. +type Source struct { + config Config + earlyExpiry time.Duration + now func() time.Time + + mu sync.Mutex + token Token + refreshing *refreshState +} + +type refreshState struct { + done chan struct{} + token string + err error +} + +var _ auth.TokenSource = (*Source)(nil) + +// SourceOption configures a refreshable token source. +type SourceOption func(*Source) error + +// WithEarlyExpiry refreshes before the token's expiry by d. The default is +// thirty seconds. A negative value is rejected. +func WithEarlyExpiry(d time.Duration) SourceOption { + return func(source *Source) error { + if d < 0 { + return fmt.Errorf("%w: early expiry cannot be negative", ErrInvalidConfig) + } + source.earlyExpiry = d + return nil + } +} + +// WithClock replaces the clock used for expiry checks. It is intended for +// deterministic tests and should not normally be used by applications. +func WithClock(now func() time.Time) SourceOption { + return func(source *Source) error { + if now == nil { + return fmt.Errorf("%w: clock cannot be nil", ErrInvalidConfig) + } + source.now = now + return nil + } +} + +// NewTokenSource creates a refreshable auth.TokenSource from an OAuth token. +// The initial token may already be expired if it has a refresh token; the +// first call then refreshes it. Token persistence is intentionally left to +// the caller so the SDK never writes credentials unexpectedly. +func NewTokenSource(config Config, initial Token, opts ...SourceOption) (*Source, error) { + if err := config.validateTokenRequest(); err != nil { + return nil, err + } + if strings.TrimSpace(initial.AccessToken) == "" && strings.TrimSpace(initial.RefreshToken) == "" { + return nil, ErrInvalidToken + } + if strings.TrimSpace(initial.AccessToken) != "" && !validAccessToken(initial.AccessToken) { + return nil, fmt.Errorf("%w: access token contains invalid characters", ErrInvalidToken) + } + if initial.TokenType == "" { + initial.TokenType = "Bearer" + } + if !strings.EqualFold(initial.TokenType, "Bearer") { + return nil, fmt.Errorf("%w: unsupported token type %q", ErrInvalidToken, initial.TokenType) + } + source := &Source{ + config: config, + earlyExpiry: defaultEarlyExpiry, + now: time.Now, + token: initial, + } + for _, opt := range opts { + if opt == nil { + continue + } + if err := opt(source); err != nil { + return nil, err + } + } + return source, nil +} + +// Token returns a current access token, refreshing it when it is expired or +// within the configured early-expiry window. +func (s *Source) Token(ctx context.Context) (string, error) { + if s == nil { + return "", ErrInvalidToken + } + if ctx == nil { + ctx = context.Background() + } + if err := ctx.Err(); err != nil { + return "", err + } + + s.mu.Lock() + if s.token.Valid(s.now(), s.earlyExpiry) { + token := s.token.AccessToken + s.mu.Unlock() + return token, nil + } + if strings.TrimSpace(s.token.RefreshToken) == "" { + s.mu.Unlock() + return "", ErrRefreshTokenUnavailable + } + if current := s.refreshing; current != nil { + s.mu.Unlock() + select { + case <-current.done: + if current.err != nil { + return "", fmt.Errorf("%w: %w", ErrTokenRefresh, current.err) + } + return current.token, nil + case <-ctx.Done(): + return "", ctx.Err() + } + } + + current := &refreshState{done: make(chan struct{})} + s.refreshing = current + refreshToken := s.token.RefreshToken + s.mu.Unlock() + + // A refresh is shared by all callers, but each caller still owns its wait. + // Detach the refresh operation from the leader's cancellation so a short + // request deadline cannot make otherwise healthy concurrent callers fail. + refreshCtx, refreshCancel := context.WithTimeout(context.WithoutCancel(ctx), defaultTokenTimeout) + go func() { + defer refreshCancel() + refreshed, err := s.config.Refresh(refreshCtx, refreshToken) + if err == nil { + if refreshed.RefreshToken == "" { + refreshed.RefreshToken = refreshToken + } + if refreshed.TokenType == "" { + refreshed.TokenType = "Bearer" + } + } + + s.mu.Lock() + if err == nil { + s.token = *refreshed + current.token = refreshed.AccessToken + } else { + current.err = err + } + s.refreshing = nil + close(current.done) + s.mu.Unlock() + }() + + select { + case <-current.done: + if current.err != nil { + return "", fmt.Errorf("%w: %w", ErrTokenRefresh, current.err) + } + return current.token, nil + case <-ctx.Done(): + return "", ctx.Err() + } +} + +func (c Config) validate() error { + if err := c.validateTokenRequest(); err != nil { + return err + } + if err := validateHTTPSURL(c.Endpoint.AuthURL, "authorization endpoint"); err != nil { + return err + } + if err := validateRedirectURL(c.RedirectURL); err != nil { + return err + } + if _, err := normalizedScopesChecked(c.Scopes); err != nil { + return err + } + return nil +} + +func (c Config) validateTokenRequest() error { + if strings.TrimSpace(c.ClientID) == "" { + return fmt.Errorf("%w: client ID is required", ErrInvalidConfig) + } + if err := validateHTTPSURL(c.Endpoint.TokenURL, "token endpoint"); err != nil { + return err + } + return nil +} + +func validateHTTPSURL(raw, name string) error { + parsed, err := url.Parse(strings.TrimSpace(raw)) + if err != nil || parsed.Host == "" || !strings.EqualFold(parsed.Scheme, "https") || parsed.User != nil || parsed.RawQuery != "" || parsed.Fragment != "" { + return fmt.Errorf("%w: %s must be an HTTPS URL without userinfo, query, or fragment", ErrInvalidConfig, name) + } + return nil +} + +func validAccessToken(value string) bool { + if strings.TrimSpace(value) == "" { + return false + } + for i := 0; i < len(value); i++ { + char := value[i] + if (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || + (char >= '0' && char <= '9') || strings.ContainsRune("-._~+/=", rune(char)) { + continue + } + return false + } + return true +} + +func validateRedirectURL(raw string) error { + parsed, err := url.Parse(strings.TrimSpace(raw)) + if err != nil || parsed.Host == "" || parsed.User != nil || parsed.RawQuery != "" || parsed.Fragment != "" || parsed.Path == "" { + return fmt.Errorf("%w: redirect URL must be absolute and cannot contain userinfo, query, or fragment", ErrInvalidRedirectURL) + } + if !strings.EqualFold(parsed.Scheme, "https") && !strings.EqualFold(parsed.Scheme, "http") { + return fmt.Errorf("%w: redirect URL must use HTTPS or loopback HTTP", ErrInvalidRedirectURL) + } + if strings.EqualFold(parsed.Scheme, "http") && !isLoopbackHost(parsed.Hostname()) { + return fmt.Errorf("%w: HTTP redirects are allowed only on loopback hosts", ErrInvalidRedirectURL) + } + return nil +} + +func validateLoopbackRedirect(raw string) error { + if err := validateRedirectURL(raw); err != nil { + return err + } + parsed, _ := url.Parse(strings.TrimSpace(raw)) + if !strings.EqualFold(parsed.Scheme, "http") || !isLoopbackHost(parsed.Hostname()) || parsed.Port() == "" || parsed.Port() == "0" { + return fmt.Errorf("%w: Login requires a fixed HTTP loopback redirect port", ErrInvalidRedirectURL) + } + return nil +} + +func isLoopbackHost(host string) bool { + if strings.EqualFold(host, "localhost") { + return true + } + ip := net.ParseIP(host) + return ip != nil && ip.IsLoopback() +} + +func normalizedScopes(scopes []string) string { + normalized, _ := normalizedScopesChecked(scopes) + // Gemini's OAuth authorization endpoint uses a comma-delimited scope + // parameter, matching the existing Markets CLI contract. + return strings.Join(normalized, ",") +} + +func normalizedScopesChecked(scopes []string) ([]string, error) { + normalized := make([]string, 0, len(scopes)) + for _, raw := range scopes { + scope := strings.TrimSpace(raw) + if scope == "" || strings.ContainsAny(scope, " \t\r\n") { + return nil, fmt.Errorf("%w: scopes must be non-empty single values", ErrInvalidConfig) + } + normalized = append(normalized, scope) + } + return normalized, nil +} + +func validateState(state string) error { + if strings.TrimSpace(state) == "" || strings.ContainsAny(state, "\r\n") { + return fmt.Errorf("%w: state is required", ErrInvalidPKCE) + } + return nil +} + +func validateVerifier(verifier string) error { + if len(verifier) < 43 || len(verifier) > 128 || strings.ContainsAny(verifier, " \t\r\n") { + return fmt.Errorf("%w: verifier must be 43 to 128 characters", ErrInvalidPKCE) + } + for _, char := range verifier { + if !(char >= 'A' && char <= 'Z') && !(char >= 'a' && char <= 'z') && !(char >= '0' && char <= '9') && !strings.ContainsRune("-._~", char) { + return fmt.Errorf("%w: verifier contains an invalid character", ErrInvalidPKCE) + } + } + return nil +} + +func pkceChallenge(verifier string) string { + digest := sha256.Sum256([]byte(verifier)) + return base64.RawURLEncoding.EncodeToString(digest[:]) +} + +func secureStringEqual(left, right string) bool { + if len(left) != len(right) { + return false + } + return subtle.ConstantTimeCompare([]byte(left), []byte(right)) == 1 +} + +type tokenResponse struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + TokenType string `json:"token_type"` + ExpiresIn *int64 `json:"expires_in"` + Scope string `json:"scope"` + Error string `json:"error"` + Description string `json:"error_description"` +} + +// TokenEndpointError describes a non-success OAuth token response without +// retaining or exposing the response body, which may contain sensitive data. +type TokenEndpointError struct { + StatusCode int + Code string + Description string +} + +func (e *TokenEndpointError) Error() string { + if e == nil { + return "gemini oauth: token endpoint error" + } + message := fmt.Sprintf("gemini oauth: token endpoint returned HTTP %d", e.StatusCode) + if e.Code != "" { + message += ": " + e.Code + } + return message +} + +func (e *TokenEndpointError) Unwrap() error { return ErrTokenEndpoint } + +func (c Config) tokenRequest(ctx context.Context, form url.Values) (*Token, error) { + if ctx == nil { + ctx = context.Background() + } + req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.Endpoint.TokenURL, strings.NewReader(form.Encode())) + if err != nil { + return nil, fmt.Errorf("create token request: %w", err) + } + req.Header.Set("Accept", "application/json") + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + client := c.tokenHTTPClient() + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("token request: %w", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(io.LimitReader(resp.Body, maxTokenResponseBytes+1)) + if err != nil { + return nil, fmt.Errorf("read token response: %w", err) + } + if len(body) > maxTokenResponseBytes { + return nil, fmt.Errorf("%w: token response exceeds %d bytes", ErrInvalidToken, maxTokenResponseBytes) + } + + var response tokenResponse + decodeErr := json.Unmarshal(body, &response) + if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices || response.Error != "" { + return nil, &TokenEndpointError{StatusCode: resp.StatusCode, Code: response.Error, Description: response.Description} + } + if decodeErr != nil { + return nil, fmt.Errorf("%w: decode token response: %v", ErrInvalidToken, decodeErr) + } + if !validAccessToken(response.AccessToken) { + return nil, fmt.Errorf("%w: token response has no usable access token", ErrInvalidToken) + } + if response.ExpiresIn != nil && *response.ExpiresIn < 0 { + return nil, fmt.Errorf("%w: token expiry is negative", ErrInvalidToken) + } + tokenType := response.TokenType + if tokenType == "" { + tokenType = "Bearer" + } + if !strings.EqualFold(tokenType, "Bearer") { + return nil, fmt.Errorf("%w: unsupported token type %q", ErrInvalidToken, tokenType) + } + token := &Token{ + AccessToken: response.AccessToken, + RefreshToken: response.RefreshToken, + TokenType: "Bearer", + Scope: response.Scope, + } + if response.ExpiresIn != nil { + if *response.ExpiresIn > int64((time.Duration(1<<63-1))/time.Second) { + return nil, fmt.Errorf("%w: token expiry is too large", ErrInvalidToken) + } + token.ExpiresAt = time.Now().Add(time.Duration(*response.ExpiresIn) * time.Second) + } + return token, nil +} + +func (c Config) tokenHTTPClient() *http.Client { + client := c.HTTPClient + if client == nil { + client = &http.Client{} + } + clone := *client + clone.CheckRedirect = func(*http.Request, []*http.Request) error { + return ErrRedirectNotAllowed + } + clone.Jar = nil + if clone.Timeout == 0 { + clone.Timeout = defaultTokenTimeout + } + return &clone +} + +func (c Config) loopbackCallback(ctx context.Context, authURL string, openBrowser BrowserOpener) (string, string, error) { + parsed, err := url.Parse(c.RedirectURL) + if err != nil { + return "", "", err + } + authorizationURL, err := url.Parse(authURL) + if err != nil { + return "", "", fmt.Errorf("parse OAuth authorization URL: %w", err) + } + expectedState := authorizationURL.Query().Get("state") + if err := validateState(expectedState); err != nil { + return "", "", err + } + listenHost := parsed.Hostname() + listeners, err := listenLoopback(listenHost, parsed.Port()) + if err != nil { + return "", "", fmt.Errorf("listen for OAuth callback: %w", err) + } + + resultCh := make(chan callbackResult, 1) + var delivered atomic.Bool + mux := http.NewServeMux() + mux.HandleFunc(parsed.EscapedPath(), func(writer http.ResponseWriter, request *http.Request) { + if len(request.RequestURI) > 8<<10 { + http.Error(writer, "request URI too long", http.StatusRequestURITooLong) + return + } + if request.Method != http.MethodGet { + writer.Header().Set("Allow", http.MethodGet) + http.Error(writer, "method not allowed", http.StatusMethodNotAllowed) + return + } + query := request.URL.Query() + returnedState := query.Get("state") + if !secureStringEqual(expectedState, returnedState) { + writeCallbackResponse(writer, http.StatusBadRequest, "Invalid authorization state.") + return + } + if query.Get("error") != "" { + if delivered.CompareAndSwap(false, true) { + resultCh <- callbackResult{state: returnedState, err: &AuthorizationError{Code: query.Get("error"), Description: query.Get("error_description")}} + } + writeCallbackResponse(writer, http.StatusOK, "Authorization was denied. You may close this window.") + return + } + code := query.Get("code") + if code == "" { + writeCallbackResponse(writer, http.StatusBadRequest, "Authorization code is missing.") + return + } + if delivered.CompareAndSwap(false, true) { + resultCh <- callbackResult{code: code, state: returnedState} + } + writeCallbackResponse(writer, http.StatusOK, "Authorization complete. You may close this window.") + }) + + server := &http.Server{Handler: mux, ReadHeaderTimeout: 5 * time.Second} + serveErr := make(chan error, len(listeners)) + for _, listener := range listeners { + go func(listener net.Listener) { + if err := server.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) { + serveErr <- err + } + }(listener) + } + defer func() { + _ = server.Close() + }() + + if len(listeners) == 0 { + return "", "", errors.New("no loopback callback listeners available") + } + + if err := openBrowser(authURL); err != nil { + return "", "", fmt.Errorf("open OAuth authorization URL: %w", err) + } + + select { + case result := <-resultCh: + return result.code, result.state, result.err + case err := <-serveErr: + return "", "", fmt.Errorf("serve OAuth callback: %w", err) + case <-ctx.Done(): + return "", "", ctx.Err() + } +} + +func listenLoopback(host, port string) ([]net.Listener, error) { + type listenTarget struct { + network string + address string + } + + var targets []listenTarget + switch { + case strings.EqualFold(host, "localhost"): + // Browsers may resolve localhost to either loopback family. Bind both + // exact loopback addresses when the platform permits it; neither target + // exposes the callback server on a non-loopback interface. + targets = []listenTarget{ + {network: "tcp4", address: net.JoinHostPort("127.0.0.1", port)}, + {network: "tcp6", address: net.JoinHostPort("::1", port)}, + } + default: + ip := net.ParseIP(host) + if ip == nil || !ip.IsLoopback() { + return nil, fmt.Errorf("callback host %q is not loopback", host) + } + network := "tcp6" + if ip.To4() != nil { + network = "tcp4" + } + targets = []listenTarget{{network: network, address: net.JoinHostPort(host, port)}} + } + + listeners := make([]net.Listener, 0, len(targets)) + var errs []error + for _, target := range targets { + listener, err := net.Listen(target.network, target.address) + if err != nil { + errs = append(errs, fmt.Errorf("%s %s: %w", target.network, target.address, err)) + continue + } + listeners = append(listeners, listener) + } + if len(listeners) == 0 { + return nil, errors.Join(errs...) + } + return listeners, nil +} + +type callbackResult struct { + code string + state string + err error +} + +// AuthorizationError reports an authorization-server denial without exposing +// callback URLs or authorization codes. +type AuthorizationError struct { + Code string + Description string +} + +func (e *AuthorizationError) Error() string { + if e == nil { + return "gemini oauth: authorization failed" + } + if e.Description == "" { + return fmt.Sprintf("gemini oauth: authorization failed: %s", e.Code) + } + return fmt.Sprintf("gemini oauth: authorization failed: %s: %s", e.Code, e.Description) +} + +func writeCallbackResponse(writer http.ResponseWriter, status int, message string) { + writer.Header().Set("Cache-Control", "no-store") + writer.Header().Set("Content-Type", "text/plain; charset=utf-8") + writer.WriteHeader(status) + _ = callbackResponseTemplate.Execute(writer, message) +} diff --git a/packages/sdk-go/oauth/oauth_test.go b/packages/sdk-go/oauth/oauth_test.go new file mode 100644 index 0000000..ef4aa7c --- /dev/null +++ b/packages/sdk-go/oauth/oauth_test.go @@ -0,0 +1,544 @@ +package oauth + +import ( + "context" + "crypto/sha256" + "encoding/base64" + "errors" + "fmt" + "net" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "sync" + "sync/atomic" + "testing" + "time" +) + +const testVerifier = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~" + +func TestGeneratePKCE(t *testing.T) { + verifier, challenge, err := GeneratePKCE() + if err != nil { + t.Fatalf("GeneratePKCE() error = %v", err) + } + if err := validateVerifier(verifier); err != nil { + t.Fatalf("generated verifier is invalid: %v", err) + } + want := sha256.Sum256([]byte(verifier)) + if got := base64.RawURLEncoding.EncodeToString(want[:]); got != challenge { + t.Fatalf("challenge = %q, want %q", challenge, got) + } + secondVerifier, _, err := GeneratePKCE() + if err != nil { + t.Fatalf("second GeneratePKCE() error = %v", err) + } + if verifier == secondVerifier { + t.Fatal("GeneratePKCE returned the same verifier twice") + } +} + +func TestTokenFormattingDoesNotExposeCredentials(t *testing.T) { + token := Token{ + AccessToken: "access-token-secret", + RefreshToken: "refresh-token-secret", + TokenType: "Bearer", + ExpiresAt: time.Unix(123, 0), + Scope: "account:read", + } + formatted := fmt.Sprintf("%v %#v", token, token) + if strings.Contains(formatted, "access-token-secret") || strings.Contains(formatted, "refresh-token-secret") { + t.Fatalf("token formatting exposed credentials: %s", formatted) + } + if !strings.Contains(formatted, "") { + t.Fatalf("token formatting omitted redaction marker: %s", formatted) + } +} + +func TestConfigFormattingDoesNotExposeClientSecret(t *testing.T) { + cfg := Config{ + ClientID: "client-id", + ClientSecret: "client-secret", + Endpoint: Endpoint{AuthURL: "https://exchange.example/auth", TokenURL: "https://exchange.example/token"}, + RedirectURL: "http://localhost:8787/callback", + Scopes: []string{"account:read"}, + } + formatted := fmt.Sprintf("%v %#v", cfg, cfg) + if strings.Contains(formatted, cfg.ClientSecret) { + t.Fatalf("OAuth config formatting exposed client secret: %s", formatted) + } + if !strings.Contains(formatted, "") { + t.Fatalf("OAuth config formatting omitted redaction marker: %s", formatted) + } +} + +func TestAuthCodeURLIncludesPKCEWithoutSecrets(t *testing.T) { + cfg := Config{ + ClientID: "cli-client-id", + ClientSecret: "do-not-put-this-in-a-url", + Endpoint: Endpoint{AuthURL: "https://exchange.example/auth", TokenURL: "https://exchange.example/auth/token"}, + RedirectURL: "http://localhost:8787/callback", + Scopes: []string{"account:read", "orders:create"}, + } + got, err := cfg.AuthCodeURL("state-value", testVerifier) + if err != nil { + t.Fatalf("AuthCodeURL() error = %v", err) + } + parsed, err := url.Parse(got) + if err != nil { + t.Fatalf("parse AuthCodeURL() result: %v", err) + } + query := parsed.Query() + if query.Get("client_id") != cfg.ClientID || query.Get("response_type") != "code" || query.Get("redirect_uri") != cfg.RedirectURL { + t.Fatalf("unexpected authorization query: %v", query) + } + if query.Get("code_challenge_method") != "S256" || query.Get("code_challenge") != pkceChallenge(testVerifier) { + t.Fatalf("unexpected PKCE query: %v", query) + } + if query.Get("scope") != "account:read,orders:create" { + t.Fatalf("scope = %q", query.Get("scope")) + } + if strings.Contains(got, cfg.ClientSecret) || strings.Contains(got, "code_verifier") { + t.Fatalf("authorization URL contains sensitive PKCE/client-secret data: %s", got) + } +} + +func TestConfigRejectsInsecureEndpointsAndRedirects(t *testing.T) { + cfg := validConfig("https://exchange.example") + cfg.Endpoint.TokenURL = "http://exchange.example/token" + if _, err := cfg.AuthCodeURL("state", testVerifier); !errors.Is(err, ErrInvalidConfig) { + t.Fatalf("AuthCodeURL() error = %v, want ErrInvalidConfig", err) + } + + cfg = validConfig("https://exchange.example") + cfg.RedirectURL = "http://example.com/callback" + if _, err := cfg.AuthCodeURL("state", testVerifier); !errors.Is(err, ErrInvalidRedirectURL) { + t.Fatalf("AuthCodeURL() error = %v, want ErrInvalidRedirectURL", err) + } + + cfg = validConfig("https://exchange.example") + cfg.RedirectURL = "https://example.com/callback?secret=not-allowed" + if _, err := cfg.AuthCodeURL("state", testVerifier); !errors.Is(err, ErrInvalidRedirectURL) { + t.Fatalf("AuthCodeURL() error = %v, want ErrInvalidRedirectURL", err) + } +} + +func TestAuthorizeExchangesCodeWithPKCE(t *testing.T) { + var authorizationQuery url.Values + server := httptest.NewTLSServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + if request.URL.Path != "/token" { + http.NotFound(writer, request) + return + } + if request.Method != http.MethodPost || request.Header.Get("Authorization") != "" { + t.Errorf("unexpected token request: method=%s authorization=%q", request.Method, request.Header.Get("Authorization")) + } + if err := request.ParseForm(); err != nil { + t.Errorf("ParseForm() error = %v", err) + } + if request.Form.Get("grant_type") != "authorization_code" || request.Form.Get("client_id") != "client-id" || request.Form.Get("code") != "auth-code" { + t.Errorf("unexpected token form: %v", request.Form) + } + if request.Form.Get("redirect_uri") != "http://localhost:8787/callback" { + t.Errorf("redirect_uri = %q", request.Form.Get("redirect_uri")) + } + if authorizationQuery.Get("code_challenge") != pkceChallenge(request.Form.Get("code_verifier")) { + t.Errorf("code verifier did not match authorization challenge") + } + writer.Header().Set("Content-Type", "application/json") + _, _ = writer.Write([]byte(`{"access_token":"access-token","refresh_token":"refresh-token","token_type":"Bearer","expires_in":3600,"scope":"account:read"}`)) + })) + defer server.Close() + + cfg := validConfig(server.URL) + cfg.HTTPClient = server.Client() + token, err := cfg.Authorize(context.Background(), func(_ context.Context, authURL string) (string, string, error) { + parsed, parseErr := url.Parse(authURL) + if parseErr != nil { + return "", "", parseErr + } + authorizationQuery = parsed.Query() + return "auth-code", authorizationQuery.Get("state"), nil + }) + if err != nil { + t.Fatalf("Authorize() error = %v", err) + } + if token.AccessToken != "access-token" || token.RefreshToken != "refresh-token" || token.TokenType != "Bearer" || token.Scope != "account:read" { + t.Fatalf("unexpected token: %+v", token) + } + if token.ExpiresAt.IsZero() { + t.Fatal("expected token expiry") + } +} + +func TestAuthorizeRejectsStateMismatchBeforeTokenExchange(t *testing.T) { + var exchanges atomic.Int32 + server := httptest.NewTLSServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + exchanges.Add(1) + writer.WriteHeader(http.StatusInternalServerError) + })) + defer server.Close() + + cfg := validConfig(server.URL) + cfg.HTTPClient = server.Client() + _, err := cfg.Authorize(context.Background(), func(context.Context, string) (string, string, error) { + return "auth-code", "wrong-state", nil + }) + if !errors.Is(err, ErrStateMismatch) { + t.Fatalf("Authorize() error = %v, want ErrStateMismatch", err) + } + if exchanges.Load() != 0 { + t.Fatalf("token endpoint called %d times after state mismatch", exchanges.Load()) + } +} + +func TestLoginRejectsInvalidCallbackStateAndThenAcceptsValidCallback(t *testing.T) { + server := httptest.NewTLSServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + writer.Header().Set("Content-Type", "application/json") + _, _ = writer.Write([]byte(`{"access_token":"access-token","refresh_token":"refresh-token","token_type":"Bearer"}`)) + })) + defer server.Close() + + port := freeLoopbackPort(t) + cfg := validConfig(server.URL) + cfg.RedirectURL = fmt.Sprintf("http://127.0.0.1:%d/callback", port) + cfg.HTTPClient = server.Client() + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + token, err := cfg.Login(ctx, func(authURL string) error { + parsed, parseErr := url.Parse(authURL) + if parseErr != nil { + return parseErr + } + callback := cfg.RedirectURL + "?code=wrong-code&state=wrong-state" + response, requestErr := http.Get(callback) + if requestErr != nil { + return requestErr + } + _ = response.Body.Close() + if response.StatusCode != http.StatusBadRequest { + return fmt.Errorf("wrong-state callback status = %d", response.StatusCode) + } + callback = cfg.RedirectURL + "?code=auth-code&state=" + url.QueryEscape(parsed.Query().Get("state")) + response, requestErr = http.Get(callback) + if requestErr != nil { + return requestErr + } + _ = response.Body.Close() + if response.StatusCode != http.StatusOK { + return fmt.Errorf("valid callback status = %d", response.StatusCode) + } + return nil + }) + if err != nil { + t.Fatalf("Login() error = %v", err) + } + if token.AccessToken != "access-token" { + t.Fatalf("unexpected token: %+v", token) + } +} + +func TestListenLoopbackBindsOnlyLoopbackAddresses(t *testing.T) { + listeners, err := listenLoopback("localhost", fmt.Sprintf("%d", freeLoopbackPort(t))) + if err != nil { + t.Fatalf("listenLoopback() error = %v", err) + } + for _, listener := range listeners { + listener := listener + t.Cleanup(func() { _ = listener.Close() }) + host, _, err := net.SplitHostPort(listener.Addr().String()) + if err != nil { + t.Fatalf("split listener address %q: %v", listener.Addr(), err) + } + ip := net.ParseIP(host) + if ip == nil || !ip.IsLoopback() { + t.Fatalf("listener bound to non-loopback address %q", listener.Addr()) + } + } +} + +func TestWriteCallbackResponseEscapesBody(t *testing.T) { + recorder := httptest.NewRecorder() + writeCallbackResponse(recorder, http.StatusOK, "") + + if strings.Contains(recorder.Body.String(), "