diff --git a/.github/workflows/dev-smoketest.yaml b/.github/workflows/dev-smoketest.yaml deleted file mode 100644 index b38a597124..0000000000 --- a/.github/workflows/dev-smoketest.yaml +++ /dev/null @@ -1,136 +0,0 @@ -name: dev-smoketest -on: - pull_request: - branches: [main] - -concurrency: - group: dev-smoketest-${{ github.head_ref }} - cancel-in-progress: true - -jobs: - smoketest: - name: Hit smoketests against Charts in Dev Setup - runs-on: self-hosted - steps: - - uses: actions/checkout@v3 - - uses: AbsaOSS/k3d-action@v2 - name: "Create Single Cluster" - with: - cluster-name: "k3s-default" - args: >- - --image rancher/k3s:v1.27.4-k3s1 - -v "$(pwd):/charts" - --k3s-arg --disable=traefik@server:0 - --k3s-arg --disable=servicelb@server:0 - - name: Deploy Infra over K3D in Dev Mode - run: | - pushd dev && source ./.envrc - make init - make deploy-services - - name: Deploy Charts in Dev - uses: nick-fields/retry@v2 - with: - timeout_minutes: 30 - retry_on: error - max_attempts: 3 - command: pushd dev && source ./.envrc && make deploy - - name: Wait for Ready - run: | - echo "Stack takes about 2 minutes to startup, waiting..." - sleep 2m - - name: Bitcoin Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=bitcoind ./dev-smoketest-settings.sh && \ - ./bitcoind-smoketest.sh regtest && \ - rm -rf smoketest-settings" - - name: LND Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=lnd ./dev-smoketest-settings.sh && \ - ./lnd-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Fulcrum Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=fulcrum ./dev-smoketest-settings.sh && \ - ./fulcrum-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Mempool Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=mempool ./dev-smoketest-settings.sh && \ - ./mempool-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Loop Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=loop ./dev-smoketest-settings.sh && \ - ./loop-smoketest.sh && \ - rm -rf smoketest-settings" - - name: RTL Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=rtl ./dev-smoketest-settings.sh && \ - ./rtl-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Galoy Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=galoy ./dev-smoketest-settings.sh && \ - ./galoy-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Monitoring Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=monitoring ./dev-smoketest-settings.sh && \ - ./monitoring-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Admin Panel Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=admin-panel ./dev-smoketest-settings.sh && \ - ./admin-panel-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Galoy Pay Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=galoy-pay ./dev-smoketest-settings.sh && \ - ./galoy-pay-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Web Wallet Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=web-wallet ./dev-smoketest-settings.sh && \ - ./web-wallet-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Bria Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=bria ./dev-smoketest-settings.sh && \ - ./bria-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Kafka Connect Smoketest - run: | - pushd dev && source ./.envrc - kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ - CHART=kafka-connect ./dev-smoketest-settings.sh && \ - ./kafka-connect-smoketest.sh && \ - rm -rf smoketest-settings" - - name: Clean Up - if: always() - run: | - rm -rf ci/tasks/smoketest-settings - k3d cluster delete --all diff --git a/.github/workflows/tilt.yaml b/.github/workflows/tilt.yaml new file mode 100644 index 0000000000..2c1b02b4e6 --- /dev/null +++ b/.github/workflows/tilt.yaml @@ -0,0 +1,85 @@ +name: "Tilt CI" +on: + pull_request: + branches: [ main ] +jobs: + tilt-ci: + runs-on: self-hosted + steps: + - uses: actions/checkout@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - uses: AbsaOSS/k3d-action@v2 + name: "Create Single Cluster" + with: + cluster-name: "k3s-default" + args: >- + --image rancher/k3s:v1.27.4-k3s1 + -v "$(pwd):/charts" + --k3s-arg --disable=traefik@server:0 + --k3s-arg --disable=servicelb@server:0 + - name: Tilt CI + run: | + pushd dev + for i in {1..5}; do + echo "Tilt CI attempt $i" + nix develop -c tilt ci && exit 0 || sleep 60 + done + exit 1 + - name: Galoy Smoketest + run: | + pushd dev + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=galoy ./dev-smoketest-settings.sh && \ + ./galoy-smoketest.sh && \ + rm -rf smoketest-settings" + - name: Bitcoin Smoketest + run: | + pushd dev + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=bitcoind ./dev-smoketest-settings.sh && \ + ./bitcoind-smoketest.sh regtest && \ + rm -rf smoketest-settings" + - name: LND Smoketest + run: | + pushd dev + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=lnd ./dev-smoketest-settings.sh && \ + ./lnd-smoketest.sh && \ + rm -rf smoketest-settings" + - name: Loop Smoketest + run: | + pushd dev + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=loop ./dev-smoketest-settings.sh && \ + ./loop-smoketest.sh && \ + rm -rf smoketest-settings" + - name: Monitoring Smoketest + run: | + pushd dev + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=monitoring ./dev-smoketest-settings.sh && \ + ./monitoring-smoketest.sh && \ + rm -rf smoketest-settings" + - name: Galoy Pay Smoketest + run: | + pushd dev + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=galoy-pay ./dev-smoketest-settings.sh && \ + ./galoy-pay-smoketest.sh && \ + rm -rf smoketest-settings" + - name: Mempool smoketest + run: | + pushd dev + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=mempool ./dev-smoketest-settings.sh && \ + ./mempool-smoketest.sh && \ + rm -rf smoketest-settings" + - name: Clean Up + if: always() + run: | + rm -rf ci/tasks/smoketest-settings + k3d cluster delete --all diff --git a/charts/admin-panel/Chart.yaml b/charts/admin-panel/Chart.yaml index 924a71bff5..6acf382084 100644 --- a/charts/admin-panel/Chart.yaml +++ b/charts/admin-panel/Chart.yaml @@ -13,8 +13,8 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.4.1-dev +version: 0.11.1-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 0.1.53 +appVersion: 0.7.2 diff --git a/charts/admin-panel/templates/deployment.yaml b/charts/admin-panel/templates/deployment.yaml index f3f4a13709..4db7de252e 100644 --- a/charts/admin-panel/templates/deployment.yaml +++ b/charts/admin-panel/templates/deployment.yaml @@ -27,9 +27,40 @@ spec: ports: - containerPort: {{ .Values.service.port }} env: - - name: NEXT_PUBLIC_GRAPHQL_URL - value: {{ .Values.adminPanel.graphqlUrl }} - - name: NEXT_PUBLIC_GALOY_AUTH_ENDPOINT - value: {{ .Values.adminPanel.galoyAuthEndpoint }} + - name: GOOGLE_CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ template "adminPanel.fullname" . }} + key: google-oauth-client-id + - name: GOOGLE_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ template "adminPanel.fullname" . }} + key: google-oauth-client-secret + - name: NEXTAUTH_SECRET + valueFrom: + secretKeyRef: + name: {{ template "adminPanel.fullname" . }} + key: next-auth-secret + - name: GITHUB_CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ template "adminPanel.fullname" . }} + key: github-oauth-client-id + - name: GITHUB_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ template "adminPanel.fullname" . }} + key: github-oauth-client-secret + - name: AUTHORIZED_EMAILS + value: {{ .Values.adminPanel.authorizedEmails }} + - name: NEXTAUTH_URL + value: {{ .Values.adminPanel.nextAuthUrl }} + - name: ADMIN_CORE_API + value: {{ .Values.adminPanel.adminCoreApi }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .Values.otelExporterOtlpEndpoint }} + - name: TRACING_SERVICE_NAME + value: {{ .Values.tracingServiceName }} resources: {{ toYaml .Values.resources | nindent 10 }} diff --git a/charts/admin-panel/templates/secrets.yaml b/charts/admin-panel/templates/secrets.yaml new file mode 100644 index 0000000000..a86827bae8 --- /dev/null +++ b/charts/admin-panel/templates/secrets.yaml @@ -0,0 +1,15 @@ +{{- if .Values.secrets.create }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "adminPanel.fullname" . }} + labels: + app: {{ template "adminPanel.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" +type: Opaque +data: + oauth-client-id: {{ .Values.secrets.oauthClientId | b64enc | quote }} + oauth-client-secret: {{ .Values.secrets.oauthClientSecret | b64enc | quote }} + next-auth-secret: {{ .Values.secrets.nextAuthSecret | b64enc | quote }} +{{- end }} diff --git a/charts/admin-panel/values.yaml b/charts/admin-panel/values.yaml index fb644dfe4a..68a25445b9 100644 --- a/charts/admin-panel/values.yaml +++ b/charts/admin-panel/values.yaml @@ -1,13 +1,23 @@ image: repository: us.gcr.io/galoy-org/admin-panel - digest: "sha256:ff07e561cb0966af99dcf07d1028f6d7708b21f4aec63f361b277e59c1de7406" - git_ref: "91dbb97" # Not used by helm + digest: "sha256:a07fe56c63df446761f2766896e2d64d3519ec6e86037a895dc9e227a47c4188" # METADATA:: repository=https://github.com/GaloyMoney/admin-panel;commit_ref=a3c11ac;app=admin-panel; + git_ref: "ef99dc0" # Not used by helm ingress: enabled: false service: port: 3000 type: ClusterIP adminPanel: - graphqlUrl: http://localhost:4002/graphql - galoyAuthEndpoint: http://localhost:4002/auth + adminCoreApi: http://admin-api.galoy-dev-galoy.svc.cluster.local:4001/admin/graphql + nextAuthUrl: http://localhost:3000 + authorizedEmails: "satoshi@galoy.io,nakamoto@blink.sv" resources: {} +secrets: + create: true + googleOauthClientId: "" + googleOauthClientSecret: "" + nextAuthSecret: "" + githubOauthClientId: "" + githubOauthClientSecret: "" +otelExporterOtlpEndpoint: http://localhost:4318 +tracingServiceName: "admin-panel" diff --git a/charts/web-wallet/.helmignore b/charts/api-dashboard/.helmignore similarity index 100% rename from charts/web-wallet/.helmignore rename to charts/api-dashboard/.helmignore diff --git a/charts/web-wallet/Chart.yaml b/charts/api-dashboard/Chart.yaml similarity index 89% rename from charts/web-wallet/Chart.yaml rename to charts/api-dashboard/Chart.yaml index b1b63d8bd9..d0b929eb03 100644 --- a/charts/web-wallet/Chart.yaml +++ b/charts/api-dashboard/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -name: web-wallet -description: A Helm chart for the web wallet addon to Galoy +name: api-dashboard +description: A Helm chart for the api dashboard addon to Galoy # A chart can be either an 'application' or a 'library' chart. # # Application charts are a collection of templates that can be packaged into versioned archives @@ -13,8 +13,8 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.5.0-dev +version: 0.1.0-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 0.3.6 +appVersion: 0.15.3 diff --git a/charts/web-wallet/templates/_helpers.tpl b/charts/api-dashboard/templates/_helpers.tpl similarity index 93% rename from charts/web-wallet/templates/_helpers.tpl rename to charts/api-dashboard/templates/_helpers.tpl index 54b7af45e6..1de7a85d9f 100644 --- a/charts/web-wallet/templates/_helpers.tpl +++ b/charts/api-dashboard/templates/_helpers.tpl @@ -3,7 +3,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "webWallet.fullname" -}} +{{- define "apiDashboard.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} diff --git a/charts/api-dashboard/templates/deployment.yaml b/charts/api-dashboard/templates/deployment.yaml new file mode 100644 index 0000000000..fe7808d8be --- /dev/null +++ b/charts/api-dashboard/templates/deployment.yaml @@ -0,0 +1,53 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "apiDashboard.fullname" . }} + labels: + app: {{ template "apiDashboard.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" +spec: + selector: + matchLabels: + app: {{ template "apiDashboard.fullname" . }} + release: {{ .Release.Name }} + replicas: 1 + template: + metadata: + labels: + app: {{ template "apiDashboard.fullname" . }} + release: "{{ .Release.Name }}" +{{- with .Values.labels }} +{{ toYaml . | trim | indent 8 }} +{{- end }} + spec: + containers: + - name: dashboard + image: "{{ .Values.image.repository }}@{{ .Values.image.digest }}" + ports: + - containerPort: {{ .Values.service.port }} + env: + - name: HYDRA_PUBLIC + value: {{ .Values.apiDashboard.hydraPublic }} + - name: CORE_URL + value: {{ .Values.apiDashboard.coreUrl }} + - name: NEXTAUTH_URL + value: {{ .Values.apiDashboard.nextAuthUrl }} + - name: NEXTAUTH_SECRET + valueFrom: + secretKeyRef: + name: {{ template "apiDashboard.fullname" . }} + key: "next-auth-secret" + - name: CLIENT_ID + value: {{ .Values.apiDashboard.clientId }} + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ template "apiDashboard.fullname" . }} + key: "client-secret" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .Values.apiDashboard.otelExporterOtlpEndpoint }} + - name: TRACING_SERVICE_NAME + value: {{ .Values.apiDashboard.tracingServiceName }} + resources: + {{ toYaml .Values.resources | nindent 10 }} diff --git a/charts/web-wallet/templates/ingress.yaml b/charts/api-dashboard/templates/ingress.yaml similarity index 85% rename from charts/web-wallet/templates/ingress.yaml rename to charts/api-dashboard/templates/ingress.yaml index 2ee837cabd..3a029d200f 100644 --- a/charts/web-wallet/templates/ingress.yaml +++ b/charts/api-dashboard/templates/ingress.yaml @@ -2,9 +2,9 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "webWallet.fullname" . }} + name: {{ include "apiDashboard.fullname" . }} labels: - app: {{ include "webWallet.fullname" . }} + app: {{ include "apiDashboard.fullname" . }} chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" release: "{{ .Release.Name }}" annotations: @@ -23,7 +23,7 @@ spec: path: "/" backend: service: - name: {{ include "webWallet.fullname" $ }} + name: {{ include "apiDashboard.fullname" $ }} port: number: {{ $.Values.service.port }} {{- end -}} diff --git a/charts/api-dashboard/templates/secrets.yaml b/charts/api-dashboard/templates/secrets.yaml new file mode 100644 index 0000000000..9a46946586 --- /dev/null +++ b/charts/api-dashboard/templates/secrets.yaml @@ -0,0 +1,14 @@ +{{- if .Values.secrets.create }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "apiDashboard.fullname" . }} + labels: + app: {{ template "apiDashboard.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" +type: Opaque +data: + next-auth-secret: {{ .Values.secrets.nextAuthSecret }} + client-secret: {{ .Values.secrets.clientSecret }} +{{- end }} diff --git a/charts/web-wallet/templates/service.yaml b/charts/api-dashboard/templates/service.yaml similarity index 58% rename from charts/web-wallet/templates/service.yaml rename to charts/api-dashboard/templates/service.yaml index f1188d946a..b6defc3438 100644 --- a/charts/web-wallet/templates/service.yaml +++ b/charts/api-dashboard/templates/service.yaml @@ -1,17 +1,17 @@ apiVersion: v1 kind: Service metadata: - name: {{ include "webWallet.fullname" . }} + name: {{ include "apiDashboard.fullname" . }} labels: - app: {{ template "webWallet.fullname" . }} + app: {{ template "apiDashboard.fullname" . }} chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" release: "{{ .Release.Name }}" spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.port }} - targetPort: 3000 + targetPort: {{ .Values.service.port }} protocol: TCP name: http selector: - app: {{ template "webWallet.fullname" . }} + app: {{ template "apiDashboard.fullname" . }} diff --git a/charts/api-dashboard/values.yaml b/charts/api-dashboard/values.yaml new file mode 100644 index 0000000000..eea65775b6 --- /dev/null +++ b/charts/api-dashboard/values.yaml @@ -0,0 +1,20 @@ +secrets: + create: true + nextAuthSecret: "" + clientSecret: "" +apiDashboard: + hydraPublic: "http://galoy-hydra-public.galoy-dev-galoy.svc.cluster.local:4444" + coreUrl: "http://galoy-oathkeeper-proxy.galoy-dev-galoy.svc.cluster.local:4455/graphql" + nextAuthUrl: "" + clientId: "" + otelExporterOtlpEndpoint: http://localhost:4318 + tracingServiceName: "dashboard" +image: + repository: us.gcr.io/galoy-org/galoy-dashboard + digest: "sha256:baaac4ba0071b2e77fbbfbf45bfc0b6a813ea2ee89ad23822f7d64dffe878bf0" # METADATA:: repository=https://github.com/GaloyMoney/galoy;commit_ref=54b4b3d;app=dashboard; +ingress: + enabled: false +service: + port: 3000 + type: ClusterIP +resources: {} diff --git a/charts/bitcoind/Chart.yaml b/charts/bitcoind/Chart.yaml index d317a4c446..4563b39a24 100644 --- a/charts/bitcoind/Chart.yaml +++ b/charts/bitcoind/Chart.yaml @@ -13,7 +13,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.19-dev +version: 0.3.1-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. diff --git a/charts/bitcoind/templates/hpa.yaml b/charts/bitcoind/templates/hpa.yaml deleted file mode 100644 index 65314ec864..0000000000 --- a/charts/bitcoind/templates/hpa.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "bitcoind.fullname" . }} - labels: - {{- include "bitcoind.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "bitcoind.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/charts/bitcoind/templates/statefulset.yaml b/charts/bitcoind/templates/statefulset.yaml index 45d34ae0d2..b14d5e457f 100644 --- a/charts/bitcoind/templates/statefulset.yaml +++ b/charts/bitcoind/templates/statefulset.yaml @@ -10,9 +10,7 @@ metadata: {{- end }} spec: serviceName: {{ include "bitcoind.fullname" . }} -{{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} -{{- end }} selector: matchLabels: {{- include "bitcoind.selectorLabels" . | nindent 6 }} @@ -124,7 +122,7 @@ spec: {{- toYaml .Values.resources | nindent 12 }} {{- if and .Values.descriptor.secretName .Values.descriptor.secretKey }} - name: descriptor-import - image: lncm/bitcoind:v24.0.1 + image: lncm/bitcoind:v25.1 command: ['/bin/sh'] args: - '-c' diff --git a/charts/bitcoind/values.yaml b/charts/bitcoind/values.yaml index 14270124bb..f83555437f 100644 --- a/charts/bitcoind/values.yaml +++ b/charts/bitcoind/values.yaml @@ -12,7 +12,7 @@ replicaCount: 1 image: repository: lncm/bitcoind pullPolicy: IfNotPresent - tag: v24.0.1 + tag: v25.1 extraInitContainers: [] sidecarContainers: [] @@ -91,13 +91,6 @@ persistence: accessMode: ReadWriteOnce size: 750Gi -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - nodeSelector: {} tolerations: [] diff --git a/charts/bria/Chart.yaml b/charts/bria/Chart.yaml index 6d269041b7..041006d562 100644 --- a/charts/bria/Chart.yaml +++ b/charts/bria/Chart.yaml @@ -13,12 +13,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.6-dev +version: 0.9.7-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: 0.1.56 +appVersion: 0.1.85 dependencies: - name: postgresql version: 11.9.6 diff --git a/charts/bria/templates/bria-cm.yaml b/charts/bria/templates/bria-cm.yaml index ed66540e20..74d33bcf0e 100644 --- a/charts/bria/templates/bria-cm.yaml +++ b/charts/bria/templates/bria-cm.yaml @@ -11,6 +11,7 @@ data: fees: mempool_space: url: {{ .Values.bria.app.fees.mempoolSpace.url }} + number_of_retries: {{ .Values.bria.app.fees.mempoolSpace.numberOfRetries }} {{- if gt (len .Values.bria.app.security.blockedAddresses) 0 }} security: blocked_addresses: {{ toYaml .Values.bria.app.security.blockedAddresses | nindent 8 }} diff --git a/charts/bria/values.yaml b/charts/bria/values.yaml index 68e8a66734..50b6863a96 100644 --- a/charts/bria/values.yaml +++ b/charts/bria/values.yaml @@ -7,7 +7,7 @@ bria: resources: {} tracing: host: localhost - port: 4318 + port: 4317 serviceName: bria-dev app: blockchain: @@ -16,6 +16,7 @@ bria: fees: mempoolSpace: url: https://mempool.space + numberOfRetries: 3 security: blockedAddresses: [] deprecatedEncryptionKey: @@ -36,8 +37,8 @@ bria: labels: {} image: repository: us.gcr.io/galoy-org/bria - digest: "sha256:3575e5810fd56c8718e6bdc530dc3d85f083ce22a070cb4bff6fa95ab20d4620" - git_ref: "a24e420" + digest: "sha256:c08d21c17972b48715cc9b6b9c31ce4db67871d081324e464408ed996a4ff958" # METADATA:: repository=https://github.com/GaloyMoney/bria;commit_ref=30b5a13;app=bria; + git_ref: "55654e2" replicas: 2 annotations: secrets: diff --git a/charts/fulcrum/Chart.yaml b/charts/fulcrum/Chart.yaml index 57114e54e8..ae937c5230 100644 --- a/charts/fulcrum/Chart.yaml +++ b/charts/fulcrum/Chart.yaml @@ -13,8 +13,8 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.3.3-dev +version: 0.4.3-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 1.9.1 +appVersion: 1.9.7 diff --git a/charts/fulcrum/values.yaml b/charts/fulcrum/values.yaml index 64d7c2f9d3..ac3945fd54 100644 --- a/charts/fulcrum/values.yaml +++ b/charts/fulcrum/values.yaml @@ -4,7 +4,7 @@ secrets: image: repository: cculianu/fulcrum pullPolicy: IfNotPresent - tag: v1.9.1 + tag: v1.9.7 # If true, generate blocks to the bitcoind node. Will fail if bitcoind is not in regtest mode. # The bitcoind installation should be in the same namespace as the fulcrum installation. diff --git a/charts/galoy-deps/Chart.lock b/charts/galoy-deps/Chart.lock index f7aea8a56a..aaf66110df 100644 --- a/charts/galoy-deps/Chart.lock +++ b/charts/galoy-deps/Chart.lock @@ -1,18 +1,18 @@ dependencies: - name: cert-manager repository: https://charts.jetstack.io - version: v1.13.0 + version: v1.13.3 - name: ingress-nginx repository: https://kubernetes.github.io/ingress-nginx version: 4.7.1 - name: strimzi-kafka-operator repository: https://strimzi.io/charts/ - version: 0.36.1 + version: 0.39.0 - name: kube-monkey repository: https://asobti.github.io/kube-monkey/charts/repo version: 1.5.2 - name: opentelemetry-collector repository: https://open-telemetry.github.io/opentelemetry-helm-charts - version: 0.68.0 -digest: sha256:fba214ab89bb5b51d6d1983c4c98feeb92a7235183e8bbfd8b06463ddf148143 -generated: "2023-09-20T07:00:45.877660594Z" + version: 0.77.0 +digest: sha256:e2ba9f6a26f63946612f84989b6b31f0ccd861d96b80c2fb6bbac654d48d15a3 +generated: "2023-12-31T07:58:16.613654333Z" diff --git a/charts/galoy-deps/Chart.yaml b/charts/galoy-deps/Chart.yaml index 4915da5dbe..f5978f2213 100644 --- a/charts/galoy-deps/Chart.yaml +++ b/charts/galoy-deps/Chart.yaml @@ -13,7 +13,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.5.5-dev +version: 0.9.3-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. @@ -22,7 +22,7 @@ appVersion: "0.1.0" dependencies: - name: "cert-manager" repository: "https://charts.jetstack.io" - version: v1.13.0 + version: v1.13.3 condition: cert-manager.enabled - name: "ingress-nginx" repository: "https://kubernetes.github.io/ingress-nginx" @@ -30,7 +30,7 @@ dependencies: condition: ingress-nginx.enabled - name: strimzi-kafka-operator repository: https://strimzi.io/charts/ - version: 0.36.1 + version: 0.39.0 condition: strimzi-kafka-operator.enabled - name: kube-monkey alias: kubemonkey @@ -39,5 +39,5 @@ dependencies: condition: kubemonkey.enabled - name: opentelemetry-collector repository: https://open-telemetry.github.io/opentelemetry-helm-charts - version: 0.68.0 + version: 0.77.0 condition: opentelemetry-collector.enabled diff --git a/charts/galoy-deps/templates/kafka-cluster.yaml b/charts/galoy-deps/templates/kafka-cluster.yaml index 189036718e..6905f7ff73 100644 --- a/charts/galoy-deps/templates/kafka-cluster.yaml +++ b/charts/galoy-deps/templates/kafka-cluster.yaml @@ -5,7 +5,7 @@ metadata: name: kafka spec: kafka: - version: 3.4.0 + version: 3.6.0 replicas: 3 listeners: - name: plain @@ -26,13 +26,13 @@ spec: log.retention.check.interval.ms: 300000 # 5 minutes storage: type: ephemeral - resources: + resources: {{ toYaml (index .Values "strimzi-kafka-operator" "kafka" "resources") | nindent 6 }} zookeeper: replicas: 3 storage: type: ephemeral - resources: + resources: {{ toYaml (index .Values "strimzi-kafka-operator" "zookeeper" "resources") | nindent 6 }} entityOperator: userOperator: {} diff --git a/charts/galoy-deps/values.yaml b/charts/galoy-deps/values.yaml index 907ec06df7..db2f62401c 100644 --- a/charts/galoy-deps/values.yaml +++ b/charts/galoy-deps/values.yaml @@ -97,6 +97,12 @@ opentelemetry-collector: - key: code.function.params.password action: update value: "" + - key: graphql.variables.input.totpCode + action: update + value: "" + - key: graphql.variables.input.authToken + action: update + value: "" # If set to null, will be overridden with values based on k8s resource limits memory_limiter: null resourcedetection: diff --git a/charts/galoy-pay/Chart.yaml b/charts/galoy-pay/Chart.yaml index 42341a7af3..ce0b404e42 100644 --- a/charts/galoy-pay/Chart.yaml +++ b/charts/galoy-pay/Chart.yaml @@ -13,11 +13,11 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.8.3-dev +version: 0.10.8-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 0.6.20 +appVersion: 0.6.23 dependencies: - name: galoy-nostr condition: galoy-nostr.enabled diff --git a/charts/galoy-pay/templates/deployment.yaml b/charts/galoy-pay/templates/deployment.yaml index 693b68dcf7..45f96ffb26 100644 --- a/charts/galoy-pay/templates/deployment.yaml +++ b/charts/galoy-pay/templates/deployment.yaml @@ -27,12 +27,12 @@ spec: ports: - containerPort: 3000 env: - - name: NEXT_PUBLIC_GRAPHQL_URL - value: "{{ .Values.graphqlUrl }}" - - name: NEXT_PUBLIC_GRAPHQL_WEBSOCKET_URL - value: "{{ .Values.graphqlWebsocketUrl }}" - - name: GRAPHQL_URL_INTERNAL - value: "{{ .Values.graphqlUrlInternal }}" + - name: PAY_URL + value: "{{ .Values.payUrl }}" + - name: PAY_DOMAIN + value: "{{ .Values.payDomain }}" + - name: CORE_GQL_URL_INTRANET + value: "{{ .Values.coreGqlUrlIntranet }}" - name: NOSTR_PUBKEY value: "{{ .Values.nostrPubkey }}" - name: REDIS_MASTER_NAME diff --git a/charts/galoy-pay/values.yaml b/charts/galoy-pay/values.yaml index a7fb5fa26c..276d17ac60 100644 --- a/charts/galoy-pay/values.yaml +++ b/charts/galoy-pay/values.yaml @@ -1,15 +1,14 @@ image: repository: us.gcr.io/galoy-org/galoy-pay - digest: "sha256:7eb631c0c21bf3a3d1487d466b8c26799e7a3a9719a8a9326ef1ef9cccaadcdf" - git_ref: "cf1ff28" # Not used by helm + digest: "sha256:3870f8a32f18a8aacf982b9a916c9c7f0aacc3d3e8e39e5a2872f8af193a20d5" # METADATA:: repository=https://github.com/GaloyMoney/galoy;commit_ref=e446eda;app=pay; ingress: enabled: false service: port: 80 type: ClusterIP -graphqlUrl: https://domain.example/graphql -graphqlUrlInternal: http://service-name.namespace.svc.cluster.local -graphqlWebsocketUrl: wss://ws.domain.example/graphql +payUrl: https://pay.domain.com +payDomain: domain.com +coreGqlUrlIntranet: http://service-name.namespace.svc.cluster.local nostrPubkey: "pubkey" galoy-nostr: enabled: true diff --git a/charts/galoy/Chart.lock b/charts/galoy/Chart.lock index c6ed26bfe7..bbe458ac45 100644 --- a/charts/galoy/Chart.lock +++ b/charts/galoy/Chart.lock @@ -1,21 +1,24 @@ dependencies: - name: redis repository: https://charts.bitnami.com/bitnami - version: 18.0.4 + version: 18.6.1 - name: mongodb repository: https://charts.bitnami.com/bitnami - version: 13.18.4 + version: 14.4.9 - name: postgresql repository: https://charts.bitnami.com/bitnami version: 11.9.13 - name: oathkeeper repository: https://k8s.ory.sh/helm/charts - version: 0.36.0 + version: 0.38.0 - name: kratos repository: https://k8s.ory.sh/helm/charts - version: 0.36.0 + version: 0.37.1 +- name: hydra + repository: https://k8s.ory.sh/helm/charts + version: 0.38.0 - name: router repository: oci://ghcr.io/apollographql/helm-charts version: 1.25.0 -digest: sha256:018db134da65825cadb6af293311b21fbec7dff4221e9108bdc60c3554a84f4c -generated: "2023-09-20T07:01:14.008158455Z" +digest: sha256:84e48f9b8ca3384d1047aef05df5ef5cad9f7f29a07caaaca149ca7b0e80ac60 +generated: "2024-01-02T13:45:41.950353565Z" diff --git a/charts/galoy/Chart.yaml b/charts/galoy/Chart.yaml index 817a234a78..311b108fc7 100644 --- a/charts/galoy/Chart.yaml +++ b/charts/galoy/Chart.yaml @@ -12,28 +12,32 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.21.42-dev +version: 0.31.10-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 0.13.97 +appVersion: 0.19.23 dependencies: - name: redis repository: https://charts.bitnami.com/bitnami - version: 18.0.4 + version: 18.6.1 - name: mongodb repository: https://charts.bitnami.com/bitnami - version: 13.18.4 + version: 14.4.9 - name: postgresql repository: https://charts.bitnami.com/bitnami version: 11.9.13 condition: postgresql.enabled - name: oathkeeper repository: https://k8s.ory.sh/helm/charts - version: 0.36.0 + version: 0.38.0 - name: kratos repository: https://k8s.ory.sh/helm/charts - version: 0.36.0 + version: 0.37.1 + - name: hydra + repository: https://k8s.ory.sh/helm/charts + version: 0.38.0 + condition: hydra.enabled - name: router repository: oci://ghcr.io/apollographql/helm-charts version: 1.25.0 diff --git a/charts/galoy/apollo-router/api-keys-schema.graphql b/charts/galoy/apollo-router/api-keys-schema.graphql new file mode 100644 index 0000000000..3be7d40c29 --- /dev/null +++ b/charts/galoy/apollo-router/api-keys-schema.graphql @@ -0,0 +1,54 @@ +type ApiKey { + id: ID! + name: String! + createdAt: Timestamp! + revoked: Boolean! + expired: Boolean! + lastUsedAt: Timestamp + expiresAt: Timestamp + readOnly: Boolean! +} + +input ApiKeyCreateInput { + name: String! + expireInDays: Int + readOnly: Boolean! = false +} + +type ApiKeyCreatePayload { + apiKey: ApiKey! + apiKeySecret: String! +} + +input ApiKeyRevokeInput { + id: ID! +} + +type ApiKeyRevokePayload { + apiKey: ApiKey! +} + + + + + +type Mutation { + apiKeyCreate(input: ApiKeyCreateInput!): ApiKeyCreatePayload! + apiKeyRevoke(input: ApiKeyRevokeInput!): ApiKeyRevokePayload! +} + + + +scalar Timestamp + +extend type User @key(fields: "id") { + id: ID! @external + apiKeys: [ApiKey!]! +} + +extend schema @link( + url: "https://specs.apollo.dev/federation/v2.3", + import: ["@key", "@tag", "@shareable", "@inaccessible", "@override", "@external", "@provides", "@requires", "@composeDirective", "@interfaceObject"] +) +directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT +directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT diff --git a/charts/galoy/apollo-router/public-schema.graphql b/charts/galoy/apollo-router/public-schema.graphql new file mode 100644 index 0000000000..1f1c4b5723 --- /dev/null +++ b/charts/galoy/apollo-router/public-schema.graphql @@ -0,0 +1,1723 @@ +interface Account { + callbackEndpoints: [CallbackEndpoint!]! + csvTransactions(walletIds: [WalletId!]!): String! + defaultWallet: PublicWallet! + defaultWalletId: WalletId! @deprecated(reason: "Shifting property to 'defaultWallet.id'") + displayCurrency: DisplayCurrency! + id: ID! + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + walletIds: [WalletId] + ): InvoiceConnection + level: AccountLevel! + limits: AccountLimits! + notificationSettings: NotificationSettings! + pendingIncomingTransactions(walletIds: [WalletId]): [Transaction!]! + realtimePrice: RealtimePrice! + transactions( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + walletIds: [WalletId] + ): TransactionConnection + walletById(walletId: WalletId!): Wallet! + wallets: [Wallet!]! +} + +type AccountDeletePayload { + errors: [Error!]! + success: Boolean! +} + +input AccountDisableNotificationCategoryInput { + category: NotificationCategory! + channel: NotificationChannel +} + +input AccountDisableNotificationChannelInput { + channel: NotificationChannel! +} + +input AccountEnableNotificationCategoryInput { + category: NotificationCategory! + channel: NotificationChannel +} + +input AccountEnableNotificationChannelInput { + channel: NotificationChannel! +} + +enum AccountLevel { + ONE + TWO + ZERO +} + +interface AccountLimit { + """The rolling time interval in seconds that the limits would apply for.""" + interval: Seconds + + """ + The amount of cents remaining below the limit for the current 24 hour period. + """ + remainingLimit: CentAmount + + """The current maximum limit for a given 24 hour period.""" + totalLimit: CentAmount! +} + +type AccountLimits { + """ + Limits for converting between currencies among a account's own wallets. + """ + convert: [AccountLimit!]! + + """Limits for sending to other internal accounts.""" + internalSend: [AccountLimit!]! + + """Limits for withdrawing to external onchain or lightning destinations.""" + withdrawal: [AccountLimit!]! +} + +input AccountUpdateDefaultWalletIdInput { + walletId: WalletId! +} + +type AccountUpdateDefaultWalletIdPayload { + account: ConsumerAccount + errors: [Error!]! +} + +input AccountUpdateDisplayCurrencyInput { + currency: DisplayCurrency! +} + +type AccountUpdateDisplayCurrencyPayload { + account: ConsumerAccount + errors: [Error!]! +} + +type AccountUpdateNotificationSettingsPayload { + account: ConsumerAccount + errors: [Error!]! +} + +"""An Opaque Bearer token""" +scalar AuthToken + +type AuthTokenPayload { + authToken: AuthToken + errors: [Error!]! + totpRequired: Boolean +} + +""" +A wallet belonging to an account which contains a BTC balance and a list of transactions. +""" +type BTCWallet implements Wallet { + accountId: ID! + + """A balance stored in BTC.""" + balance: SignedAmount! + id: ID! + invoiceByPaymentHash(paymentHash: PaymentHash!): Invoice! + + """A list of all invoices associated with walletIds optionally passed.""" + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): InvoiceConnection + + """An unconfirmed incoming onchain balance.""" + pendingIncomingBalance: SignedAmount! + pendingIncomingTransactions: [Transaction!]! + pendingIncomingTransactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + ): [Transaction!]! + transactionById(transactionId: ID!): Transaction! + + """A list of BTC transactions associated with this wallet.""" + transactions( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): TransactionConnection + transactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): TransactionConnection + transactionsByPaymentHash(paymentHash: PaymentHash!): [Transaction!]! + walletCurrency: WalletCurrency! +} + +type BuildInformation { + commitHash: String + helmRevision: Int +} + +type CallbackEndpoint { + id: EndpointId! + url: EndpointUrl! +} + +input CallbackEndpointAddInput { + """callback endpoint to be called""" + url: EndpointUrl! +} + +type CallbackEndpointAddPayload { + errors: [Error!]! + id: EndpointId +} + +input CallbackEndpointDeleteInput { + id: EndpointId! +} + +type CaptchaCreateChallengePayload { + errors: [Error!]! + result: CaptchaCreateChallengeResult +} + +type CaptchaCreateChallengeResult { + challengeCode: String! + failbackMode: Boolean! + id: String! + newCaptcha: Boolean! +} + +input CaptchaRequestAuthCodeInput { + challengeCode: String! + channel: PhoneCodeChannelType + phone: Phone! + secCode: String! + validationCode: String! +} + +"""(Positive) Cent amount (1/100 of a dollar)""" +scalar CentAmount + +type CentAmountPayload { + amount: CentAmount + errors: [Error!]! +} + +type ConsumerAccount implements Account { + callbackEndpoints: [CallbackEndpoint!]! + + """ + return CSV stream, base64 encoded, of the list of transactions in the wallet + """ + csvTransactions(walletIds: [WalletId!]!): String! + defaultWallet: PublicWallet! + defaultWalletId: WalletId! + displayCurrency: DisplayCurrency! + id: ID! + + """A list of all invoices associated with walletIds optionally passed.""" + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + walletIds: [WalletId] + ): InvoiceConnection + level: AccountLevel! + limits: AccountLimits! + notificationSettings: NotificationSettings! + pendingIncomingTransactions(walletIds: [WalletId]): [Transaction!]! + + """List the quiz questions of the consumer account""" + quiz: [Quiz!]! + realtimePrice: RealtimePrice! + + """ + A list of all transactions associated with walletIds optionally passed. + """ + transactions( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + walletIds: [WalletId] + ): TransactionConnection + walletById(walletId: WalletId!): Wallet! + wallets: [Wallet!]! +} + +""" +An alias name that a user can set for a wallet (with which they have transactions) +""" +scalar ContactAlias + +type Coordinates { + latitude: Float! + longitude: Float! +} + +type Country { + id: CountryCode! + supportedAuthChannels: [PhoneCodeChannelType!]! +} + +"""A CCA2 country code (ex US, FR, etc)""" +scalar CountryCode + +type Currency { + flag: String! + fractionDigits: Int! + id: ID! + name: String! + symbol: String! +} + +type DepositFeesInformation { + minBankFee: String! + + """below this amount minBankFee will be charged""" + minBankFeeThreshold: String! + + """ratio to charge as basis points above minBankFeeThreshold amount""" + ratio: String! +} + +input DeviceNotificationTokenCreateInput { + deviceToken: String! +} + +"""Display currency of an account""" +scalar DisplayCurrency + +type Email { + address: EmailAddress + verified: Boolean +} + +"""Email address""" +scalar EmailAddress + +""" +An id to be passed between registrationInitiate and registrationValidate for confirming email +""" +scalar EmailRegistrationId + +scalar EndpointId + +"""Url that will be fetched on events for the account""" +scalar EndpointUrl + +interface Error { + code: String + message: String! + path: [String] +} + +enum ExchangeCurrencyUnit { + BTCSAT + USDCENT +} + +"""Feedback shared with our user""" +scalar Feedback + +input FeedbackSubmitInput { + feedback: Feedback! +} + +type FeesInformation { + deposit: DepositFeesInformation! +} + +""" +Provides global settings for the application which might have an impact for the user. +""" +type Globals { + buildInformation: BuildInformation! + feesInformation: FeesInformation! + + """ + The domain name for lightning addresses accepted by this Galoy instance + """ + lightningAddressDomain: String! + lightningAddressDomainAliases: [String!]! + + """ + Which network (mainnet, testnet, regtest, signet) this instance is running on. + """ + network: Network! + + """ + A list of public keys for the running lightning nodes. + This can be used to know if an invoice belongs to one of our nodes. + """ + nodesIds: [String!]! + + """A list of countries and their supported auth channels""" + supportedCountries: [Country!]! +} + +type GraphQLApplicationError implements Error { + code: String + message: String! + path: [String] +} + +"""Hex-encoded string of 32 bytes""" +scalar Hex32Bytes + +union InitiationVia = InitiationViaIntraLedger | InitiationViaLn | InitiationViaOnChain + +type InitiationViaIntraLedger { + counterPartyUsername: Username + counterPartyWalletId: WalletId +} + +type InitiationViaLn { + paymentHash: PaymentHash! + + """Bolt11 invoice""" + paymentRequest: LnPaymentRequest! +} + +type InitiationViaOnChain { + address: OnChainAddress! +} + +input IntraLedgerPaymentSendInput { + """Amount in satoshis.""" + amount: SatAmount! + + """Optional memo to be attached to the payment.""" + memo: Memo + recipientWalletId: WalletId! + + """The wallet ID of the sender.""" + walletId: WalletId! +} + +type IntraLedgerUpdate { + amount: SatAmount! @deprecated(reason: "Deprecated in favor of transaction") + displayCurrencyPerSat: Float! @deprecated(reason: "Deprecated in favor of transaction") + transaction: Transaction! + txNotificationType: TxNotificationType! + usdPerSat: Float! @deprecated(reason: "updated over displayCurrencyPerSat") + walletId: WalletId! @deprecated(reason: "Deprecated in favor of transaction") +} + +input IntraLedgerUsdPaymentSendInput { + """Amount in cents.""" + amount: CentAmount! + + """Optional memo to be attached to the payment.""" + memo: Memo + recipientWalletId: WalletId! + + """The wallet ID of the sender.""" + walletId: WalletId! +} + +"""A lightning invoice.""" +interface Invoice { + createdAt: Timestamp! + + """The payment hash of the lightning invoice.""" + paymentHash: PaymentHash! + + """The bolt11 invoice to be paid.""" + paymentRequest: LnPaymentRequest! + + """ + The payment secret of the lightning invoice. This is not the preimage of the payment hash. + """ + paymentSecret: LnPaymentSecret! + + """The payment status of the invoice.""" + paymentStatus: InvoicePaymentStatus! +} + +"""A connection to a list of items.""" +type InvoiceConnection { + """A list of edges.""" + edges: [InvoiceEdge!] + + """Information to aid in pagination.""" + pageInfo: PageInfo! +} + +"""An edge in a connection.""" +type InvoiceEdge { + """A cursor for use in pagination""" + cursor: String! + + """The item at the end of the edge""" + node: Invoice! +} + +enum InvoicePaymentStatus { + EXPIRED + PAID + PENDING +} + +scalar Language + +input LnAddressPaymentSendInput { + """Amount in satoshis.""" + amount: SatAmount! + + """Lightning address to send to.""" + lnAddress: String! + + """Wallet ID to send bitcoin from.""" + walletId: WalletId! +} + +type LnInvoice implements Invoice { + createdAt: Timestamp! + paymentHash: PaymentHash! + paymentRequest: LnPaymentRequest! + paymentSecret: LnPaymentSecret! + paymentStatus: InvoicePaymentStatus! + satoshis: SatAmount! +} + +input LnInvoiceCreateInput { + """Amount in satoshis.""" + amount: SatAmount! + + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """Optional memo for the lightning invoice.""" + memo: Memo + + """Wallet ID for a BTC wallet belonging to the current account.""" + walletId: WalletId! +} + +input LnInvoiceCreateOnBehalfOfRecipientInput { + """Amount in satoshis.""" + amount: SatAmount! + descriptionHash: Hex32Bytes + + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """Optional memo for the lightning invoice.""" + memo: Memo + + """Wallet ID for a BTC wallet which belongs to any account.""" + recipientWalletId: WalletId! +} + +input LnInvoiceFeeProbeInput { + paymentRequest: LnPaymentRequest! + walletId: WalletId! +} + +type LnInvoicePayload { + errors: [Error!]! + invoice: LnInvoice +} + +input LnInvoicePaymentInput { + """Optional memo to associate with the lightning invoice.""" + memo: Memo + + """Payment request representing the invoice which is being paid.""" + paymentRequest: LnPaymentRequest! + + """ + Wallet ID with sufficient balance to cover amount of invoice. Must belong to the account of the current user. + """ + walletId: WalletId! +} + +input LnInvoicePaymentStatusInput { + paymentRequest: LnPaymentRequest! +} + +type LnInvoicePaymentStatusPayload { + errors: [Error!]! + status: InvoicePaymentStatus +} + +type LnNoAmountInvoice implements Invoice { + createdAt: Timestamp! + paymentHash: PaymentHash! + paymentRequest: LnPaymentRequest! + paymentSecret: LnPaymentSecret! + paymentStatus: InvoicePaymentStatus! +} + +input LnNoAmountInvoiceCreateInput { + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """Optional memo for the lightning invoice.""" + memo: Memo + + """ + ID for either a USD or BTC wallet belonging to the account of the current user. + """ + walletId: WalletId! +} + +input LnNoAmountInvoiceCreateOnBehalfOfRecipientInput { + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """Optional memo for the lightning invoice.""" + memo: Memo + + """ + ID for either a USD or BTC wallet which belongs to the account of any user. + """ + recipientWalletId: WalletId! +} + +input LnNoAmountInvoiceFeeProbeInput { + amount: SatAmount! + paymentRequest: LnPaymentRequest! + walletId: WalletId! +} + +type LnNoAmountInvoicePayload { + errors: [Error!]! + invoice: LnNoAmountInvoice +} + +input LnNoAmountInvoicePaymentInput { + """Amount to pay in satoshis.""" + amount: SatAmount! + + """Optional memo to associate with the lightning invoice.""" + memo: Memo + + """Payment request representing the invoice which is being paid.""" + paymentRequest: LnPaymentRequest! + + """ + Wallet ID with sufficient balance to cover amount defined in mutation request. Must belong to the account of the current user. + """ + walletId: WalletId! +} + +input LnNoAmountUsdInvoiceFeeProbeInput { + amount: CentAmount! + paymentRequest: LnPaymentRequest! + walletId: WalletId! +} + +input LnNoAmountUsdInvoicePaymentInput { + """Amount to pay in USD cents.""" + amount: CentAmount! + + """Optional memo to associate with the lightning invoice.""" + memo: Memo + + """Payment request representing the invoice which is being paid.""" + paymentRequest: LnPaymentRequest! + + """ + Wallet ID with sufficient balance to cover amount defined in mutation request. Must belong to the account of the current user. + """ + walletId: WalletId! +} + +scalar LnPaymentPreImage + +"""BOLT11 lightning invoice payment request with the amount included""" +scalar LnPaymentRequest + +scalar LnPaymentSecret + +type LnUpdate { + paymentHash: PaymentHash! @deprecated(reason: "Deprecated in favor of transaction") + status: InvoicePaymentStatus! + transaction: Transaction! + walletId: WalletId! @deprecated(reason: "Deprecated in favor of transaction") +} + +input LnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipientInput { + """Amount in satoshis.""" + amount: SatAmount! + descriptionHash: Hex32Bytes + + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """ + Optional memo for the lightning invoice. Acts as a note to the recipient. + """ + memo: Memo + + """Wallet ID for a USD wallet which belongs to the account of any user.""" + recipientWalletId: WalletId! +} + +input LnUsdInvoiceCreateInput { + """Amount in USD cents.""" + amount: CentAmount! + + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """Optional memo for the lightning invoice.""" + memo: Memo + + """Wallet ID for a USD wallet belonging to the current user.""" + walletId: WalletId! +} + +input LnUsdInvoiceCreateOnBehalfOfRecipientInput { + """Amount in USD cents.""" + amount: CentAmount! + descriptionHash: Hex32Bytes + + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """ + Optional memo for the lightning invoice. Acts as a note to the recipient. + """ + memo: Memo + + """Wallet ID for a USD wallet which belongs to the account of any user.""" + recipientWalletId: WalletId! +} + +input LnUsdInvoiceFeeProbeInput { + paymentRequest: LnPaymentRequest! + walletId: WalletId! +} + +input LnurlPaymentSendInput { + """Amount in satoshis.""" + amount: SatAmount! + + """Lnurl string to send to.""" + lnurl: String! + + """Wallet ID to send bitcoin from.""" + walletId: WalletId! +} + +type MapInfo { + coordinates: Coordinates! + title: String! +} + +type MapMarker { + mapInfo: MapInfo! + username: Username +} + +"""Text field in a lightning payment transaction""" +scalar Memo + +"""(Positive) amount of minutes""" +scalar Minutes + +type MobileVersions { + currentSupported: Int! + minSupported: Int! + platform: String! +} + +type Mutation { + accountDelete: AccountDeletePayload! + accountDisableNotificationCategory(input: AccountDisableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! + accountDisableNotificationChannel(input: AccountDisableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! + accountEnableNotificationCategory(input: AccountEnableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! + accountEnableNotificationChannel(input: AccountEnableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! + accountUpdateDefaultWalletId(input: AccountUpdateDefaultWalletIdInput!): AccountUpdateDefaultWalletIdPayload! + accountUpdateDisplayCurrency(input: AccountUpdateDisplayCurrencyInput!): AccountUpdateDisplayCurrencyPayload! + callbackEndpointAdd(input: CallbackEndpointAddInput!): CallbackEndpointAddPayload! + callbackEndpointDelete(input: CallbackEndpointDeleteInput!): SuccessPayload! + captchaCreateChallenge: CaptchaCreateChallengePayload! + captchaRequestAuthCode(input: CaptchaRequestAuthCodeInput!): SuccessPayload! + deviceNotificationTokenCreate(input: DeviceNotificationTokenCreateInput!): SuccessPayload! + feedbackSubmit(input: FeedbackSubmitInput!): SuccessPayload! + + """ + Actions a payment which is internal to the ledger e.g. it does + not use onchain/lightning. Returns payment status (success, + failed, pending, already_paid). + """ + intraLedgerPaymentSend(input: IntraLedgerPaymentSendInput!): PaymentSendPayload! + + """ + Actions a payment which is internal to the ledger e.g. it does + not use onchain/lightning. Returns payment status (success, + failed, pending, already_paid). + """ + intraLedgerUsdPaymentSend(input: IntraLedgerUsdPaymentSendInput!): PaymentSendPayload! + + """Sends a payment to a lightning address.""" + lnAddressPaymentSend(input: LnAddressPaymentSendInput!): PaymentSendPayload! + + """ + Returns a lightning invoice for an associated wallet. + When invoice is paid the value will be credited to a BTC wallet. + Expires after 'expiresIn' or 24 hours. + """ + lnInvoiceCreate(input: LnInvoiceCreateInput!): LnInvoicePayload! + + """ + Returns a lightning invoice for an associated wallet. + When invoice is paid the value will be credited to a BTC wallet. + Expires after 'expiresIn' or 24 hours. + """ + lnInvoiceCreateOnBehalfOfRecipient(input: LnInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! + lnInvoiceFeeProbe(input: LnInvoiceFeeProbeInput!): SatAmountPayload! + + """ + Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. + Provided wallet can be USD or BTC and must have sufficient balance to cover amount in lightning invoice. + Returns payment status (success, failed, pending, already_paid). + """ + lnInvoicePaymentSend(input: LnInvoicePaymentInput!): PaymentSendPayload! + + """ + Returns a lightning invoice for an associated wallet. + Can be used to receive any supported currency value (currently USD or BTC). + Expires after 'expiresIn' or 24 hours for BTC invoices or 5 minutes for USD invoices. + """ + lnNoAmountInvoiceCreate(input: LnNoAmountInvoiceCreateInput!): LnNoAmountInvoicePayload! + + """ + Returns a lightning invoice for an associated wallet. + Can be used to receive any supported currency value (currently USD or BTC). + Expires after 'expiresIn' or 24 hours for BTC invoices or 5 minutes for USD invoices. + """ + lnNoAmountInvoiceCreateOnBehalfOfRecipient(input: LnNoAmountInvoiceCreateOnBehalfOfRecipientInput!): LnNoAmountInvoicePayload! + lnNoAmountInvoiceFeeProbe(input: LnNoAmountInvoiceFeeProbeInput!): SatAmountPayload! + + """ + Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. + Provided wallet must be BTC and must have sufficient balance to cover amount specified in mutation request. + Returns payment status (success, failed, pending, already_paid). + """ + lnNoAmountInvoicePaymentSend(input: LnNoAmountInvoicePaymentInput!): PaymentSendPayload! + lnNoAmountUsdInvoiceFeeProbe(input: LnNoAmountUsdInvoiceFeeProbeInput!): CentAmountPayload! + + """ + Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. + Provided wallet must be USD and have sufficient balance to cover amount specified in mutation request. + Returns payment status (success, failed, pending, already_paid). + """ + lnNoAmountUsdInvoicePaymentSend(input: LnNoAmountUsdInvoicePaymentInput!): PaymentSendPayload! + + """ + Returns a lightning invoice denominated in satoshis for an associated wallet. + When invoice is paid the equivalent value at invoice creation will be credited to a USD wallet. + Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate + associated with the amount). + """ + lnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipient(input: LnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipientInput!): LnInvoicePayload! + + """ + Returns a lightning invoice denominated in satoshis for an associated wallet. + When invoice is paid the equivalent value at invoice creation will be credited to a USD wallet. + Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate + associated with the amount). + """ + lnUsdInvoiceCreate(input: LnUsdInvoiceCreateInput!): LnInvoicePayload! + + """ + Returns a lightning invoice denominated in satoshis for an associated wallet. + When invoice is paid the equivalent value at invoice creation will be credited to a USD wallet. + Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate + associated with the amount). + """ + lnUsdInvoiceCreateOnBehalfOfRecipient(input: LnUsdInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! + lnUsdInvoiceFeeProbe(input: LnUsdInvoiceFeeProbeInput!): SatAmountPayload! + + """Sends a payment to a lightning address.""" + lnurlPaymentSend(input: LnurlPaymentSendInput!): PaymentSendPayload! + onChainAddressCreate(input: OnChainAddressCreateInput!): OnChainAddressPayload! + onChainAddressCurrent(input: OnChainAddressCurrentInput!): OnChainAddressPayload! + onChainPaymentSend(input: OnChainPaymentSendInput!): PaymentSendPayload! + onChainPaymentSendAll(input: OnChainPaymentSendAllInput!): PaymentSendPayload! + onChainUsdPaymentSend(input: OnChainUsdPaymentSendInput!): PaymentSendPayload! + onChainUsdPaymentSendAsBtcDenominated(input: OnChainUsdPaymentSendAsBtcDenominatedInput!): PaymentSendPayload! + quizClaim(input: QuizClaimInput!): QuizClaimPayload! + quizCompleted(input: QuizCompletedInput!): QuizCompletedPayload! @deprecated(reason: "Use quizClaim instead") + userContactUpdateAlias(input: UserContactUpdateAliasInput!): UserContactUpdateAliasPayload! @deprecated(reason: "will be moved to AccountContact") + userEmailDelete: UserEmailDeletePayload! + userEmailRegistrationInitiate(input: UserEmailRegistrationInitiateInput!): UserEmailRegistrationInitiatePayload! + userEmailRegistrationValidate(input: UserEmailRegistrationValidateInput!): UserEmailRegistrationValidatePayload! + userLogin(input: UserLoginInput!): AuthTokenPayload! + userLoginUpgrade(input: UserLoginUpgradeInput!): UpgradePayload! + userLogout(input: UserLogoutInput): SuccessPayload! + userPhoneDelete: UserPhoneDeletePayload! + userPhoneRegistrationInitiate(input: UserPhoneRegistrationInitiateInput!): SuccessPayload! + userPhoneRegistrationValidate(input: UserPhoneRegistrationValidateInput!): UserPhoneRegistrationValidatePayload! + userTotpDelete: UserTotpDeletePayload! + userTotpRegistrationInitiate: UserTotpRegistrationInitiatePayload! + userTotpRegistrationValidate(input: UserTotpRegistrationValidateInput!): UserTotpRegistrationValidatePayload! + userUpdateLanguage(input: UserUpdateLanguageInput!): UserUpdateLanguagePayload! + userUpdateUsername(input: UserUpdateUsernameInput!): UserUpdateUsernamePayload! @deprecated(reason: "Username will be moved to @Handle in Accounts. Also SetUsername naming should be used instead of UpdateUsername to reflect the idempotency of Handles") +} + +type MyUpdatesPayload { + errors: [Error!]! + me: User + update: UserUpdate +} + +enum Network { + mainnet + regtest + signet + testnet +} + +scalar NotificationCategory + +enum NotificationChannel { + PUSH +} + +type NotificationChannelSettings { + disabledCategories: [NotificationCategory!]! + enabled: Boolean! +} + +type NotificationSettings { + push: NotificationChannelSettings! +} + +"""An address for an on-chain bitcoin destination""" +scalar OnChainAddress + +input OnChainAddressCreateInput { + walletId: WalletId! +} + +input OnChainAddressCurrentInput { + walletId: WalletId! +} + +type OnChainAddressPayload { + address: OnChainAddress + errors: [Error!]! +} + +input OnChainPaymentSendAllInput { + address: OnChainAddress! + memo: Memo + speed: PayoutSpeed! = FAST + walletId: WalletId! +} + +input OnChainPaymentSendInput { + address: OnChainAddress! + amount: SatAmount! + memo: Memo + speed: PayoutSpeed! = FAST + walletId: WalletId! +} + +type OnChainTxFee { + amount: SatAmount! +} + +scalar OnChainTxHash + +type OnChainUpdate { + amount: SatAmount! @deprecated(reason: "Deprecated in favor of transaction") + displayCurrencyPerSat: Float! @deprecated(reason: "Deprecated in favor of transaction") + transaction: Transaction! + txHash: OnChainTxHash! @deprecated(reason: "Deprecated in favor of transaction") + txNotificationType: TxNotificationType! + usdPerSat: Float! @deprecated(reason: "updated over displayCurrencyPerSat") + walletId: WalletId! @deprecated(reason: "Deprecated in favor of transaction") +} + +input OnChainUsdPaymentSendAsBtcDenominatedInput { + address: OnChainAddress! + amount: SatAmount! + memo: Memo + speed: PayoutSpeed! = FAST + walletId: WalletId! +} + +input OnChainUsdPaymentSendInput { + address: OnChainAddress! + amount: CentAmount! + memo: Memo + speed: PayoutSpeed! = FAST + walletId: WalletId! +} + +type OnChainUsdTxFee { + amount: CentAmount! +} + +type OneDayAccountLimit implements AccountLimit { + """ + The rolling time interval value in seconds for the current 24 hour period. + """ + interval: Seconds + + """ + The amount of cents remaining below the limit for the current 24 hour period. + """ + remainingLimit: CentAmount + + """The current maximum limit for a given 24 hour period.""" + totalLimit: CentAmount! +} + +"""An authentication code valid for a single use""" +scalar OneTimeAuthCode + +"""Information about pagination in a connection.""" +type PageInfo { + """When paginating forwards, the cursor to continue.""" + endCursor: String + + """When paginating forwards, are there more items?""" + hasNextPage: Boolean! + + """When paginating backwards, are there more items?""" + hasPreviousPage: Boolean! + + """When paginating backwards, the cursor to continue.""" + startCursor: String +} + +scalar PaymentHash + +type PaymentSendPayload { + errors: [Error!]! + status: PaymentSendResult + transaction: Transaction +} + +enum PaymentSendResult { + ALREADY_PAID + FAILURE + PENDING + SUCCESS +} + +enum PayoutSpeed { + FAST +} + +"""Phone number which includes country code""" +scalar Phone + +enum PhoneCodeChannelType { + SMS + WHATSAPP +} + +""" +Price amount expressed in base/offset. To calculate, use: `base / 10^offset` +""" +type Price { + base: SafeInt! + currencyUnit: String! + formattedAmount: String! + offset: Int! +} + +"""The range for the X axis in the BTC price graph""" +enum PriceGraphRange { + FIVE_YEARS + ONE_DAY + ONE_MONTH + ONE_WEEK + ONE_YEAR +} + +input PriceInput { + amount: SatAmount! + amountCurrencyUnit: ExchangeCurrencyUnit! + priceCurrencyUnit: ExchangeCurrencyUnit! +} + +interface PriceInterface { + base: SafeInt! + currencyUnit: String! @deprecated(reason: "Deprecated due to type renaming") + offset: Int! +} + +"""Price of 1 sat in base/offset. To calculate, use: `base / 10^offset`""" +type PriceOfOneSatInMinorUnit implements PriceInterface { + base: SafeInt! + currencyUnit: String! @deprecated(reason: "Deprecated due to type renaming") + offset: Int! +} + +""" +Price of 1 sat or 1 usd cent in base/offset. To calculate, use: `base / 10^offset` +""" +type PriceOfOneSettlementMinorUnitInDisplayMinorUnit implements PriceInterface { + base: SafeInt! + currencyUnit: String! @deprecated(reason: "Deprecated due to type renaming") + formattedAmount: String! @deprecated(reason: "Deprecated please use `base / 10^offset`") + offset: Int! +} + +""" +Price of 1 usd cent in base/offset. To calculate, use: `base / 10^offset` +""" +type PriceOfOneUsdCentInMinorUnit implements PriceInterface { + base: SafeInt! + currencyUnit: String! @deprecated(reason: "Deprecated due to type renaming") + offset: Int! +} + +type PricePayload { + errors: [Error!]! + price: Price +} + +type PricePoint { + price: Price! + + """ + Unix timestamp (number of seconds elapsed since January 1, 1970 00:00:00 UTC) + """ + timestamp: Timestamp! +} + +""" +A public view of a generic wallet which stores value in one of our supported currencies. +""" +type PublicWallet { + currency: WalletCurrency! + id: ID! + walletCurrency: WalletCurrency! @deprecated(reason: "Shifting property to 'currency'") +} + +type Query { + accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! + btcPriceList(range: PriceGraphRange!): [PricePoint] + businessMapMarkers: [MapMarker] + currencyList: [Currency!]! + globals: Globals + lnInvoicePaymentStatus(input: LnInvoicePaymentStatusInput!): LnInvoicePaymentStatusPayload! + me: User + mobileVersions: [MobileVersions] + onChainTxFee(address: OnChainAddress!, amount: SatAmount!, speed: PayoutSpeed! = FAST, walletId: WalletId!): OnChainTxFee! + onChainUsdTxFee(address: OnChainAddress!, amount: CentAmount!, speed: PayoutSpeed! = FAST, walletId: WalletId!): OnChainUsdTxFee! + onChainUsdTxFeeAsBtcDenominated(address: OnChainAddress!, amount: SatAmount!, speed: PayoutSpeed! = FAST, walletId: WalletId!): OnChainUsdTxFee! + + """Returns 1 Sat and 1 Usd Cent price for the given currency""" + realtimePrice(currency: DisplayCurrency = "USD"): RealtimePrice! + userDefaultWalletId(username: Username!): WalletId! @deprecated(reason: "will be migrated to AccountDefaultWalletId") + usernameAvailable(username: Username!): Boolean +} + +type Quiz { + """The reward in Satoshis for the quiz question""" + amount: SatAmount! + completed: Boolean! + id: ID! + notBefore: Timestamp +} + +input QuizClaimInput { + id: ID! +} + +type QuizClaimPayload { + errors: [Error!]! + quizzes: [Quiz!]! +} + +input QuizCompletedInput { + id: ID! +} + +type QuizCompletedPayload { + errors: [Error!]! + quiz: Quiz +} + +type RealtimePrice { + btcSatPrice: PriceOfOneSatInMinorUnit! + denominatorCurrency: DisplayCurrency! + id: ID! + + """ + Unix timestamp (number of seconds elapsed since January 1, 1970 00:00:00 UTC) + """ + timestamp: Timestamp! + usdCentPrice: PriceOfOneUsdCentInMinorUnit! +} + +input RealtimePriceInput { + currency: DisplayCurrency = "USD" +} + +type RealtimePricePayload { + errors: [Error!]! + realtimePrice: RealtimePrice +} + +""" +Non-fractional signed whole numeric value between -(2^53) + 1 and 2^53 - 1 +""" +scalar SafeInt + +"""(Positive) Satoshi amount""" +scalar SatAmount + +type SatAmountPayload { + amount: SatAmount + errors: [Error!]! +} + +"""(Positive) amount of seconds""" +scalar Seconds + +union SettlementVia = SettlementViaIntraLedger | SettlementViaLn | SettlementViaOnChain + +type SettlementViaIntraLedger { + """ + Settlement destination: Could be null if the payee does not have a username + """ + counterPartyUsername: Username + counterPartyWalletId: WalletId +} + +type SettlementViaLn { + paymentSecret: LnPaymentSecret @deprecated(reason: "Shifting property to 'preImage' to improve granularity of the LnPaymentSecret type") + preImage: LnPaymentPreImage +} + +type SettlementViaOnChain { + arrivalInMempoolEstimatedAt: Timestamp + transactionHash: OnChainTxHash + vout: Int +} + +"""An amount (of a currency) that can be negative (e.g. in a transaction)""" +scalar SignedAmount + +""" +A string amount (of a currency) that can be negative (e.g. in a transaction) +""" +scalar SignedDisplayMajorAmount + +type Subscription { + lnInvoicePaymentStatus(input: LnInvoicePaymentStatusInput!): LnInvoicePaymentStatusPayload! + myUpdates: MyUpdatesPayload! + price(input: PriceInput!): PricePayload! + + """Returns the price of 1 satoshi""" + realtimePrice(input: RealtimePriceInput!): RealtimePricePayload! +} + +type SuccessPayload { + errors: [Error!]! + success: Boolean +} + +""" +Timestamp field, serialized as Unix time (the number of seconds since the Unix epoch) +""" +scalar Timestamp + +"""A time-based one-time password""" +scalar TotpCode + +"""An id to be passed between set and verify for confirming totp""" +scalar TotpRegistrationId + +"""A secret to generate time-based one-time password""" +scalar TotpSecret + +""" +Give details about an individual transaction. +Galoy have a smart routing system which is automatically +settling intraledger when both the payer and payee use the same wallet +therefore it's possible the transactions is being initiated onchain +or with lightning but settled intraledger. +""" +type Transaction { + createdAt: Timestamp! + direction: TxDirection! + id: ID! + + """From which protocol the payment has been initiated.""" + initiationVia: InitiationVia! + memo: Memo + + """Amount of the settlement currency sent or received.""" + settlementAmount: SignedAmount! + + """Wallet currency for transaction.""" + settlementCurrency: WalletCurrency! + settlementDisplayAmount: SignedDisplayMajorAmount! + settlementDisplayCurrency: DisplayCurrency! + settlementDisplayFee: SignedDisplayMajorAmount! + settlementFee: SignedAmount! + + """Price in WALLETCURRENCY/SETTLEMENTUNIT at time of settlement.""" + settlementPrice: PriceOfOneSettlementMinorUnitInDisplayMinorUnit! + + """To which protocol the payment has settled on.""" + settlementVia: SettlementVia! + status: TxStatus! +} + +"""A connection to a list of items.""" +type TransactionConnection { + """A list of edges.""" + edges: [TransactionEdge!] + + """Information to aid in pagination.""" + pageInfo: PageInfo! +} + +"""An edge in a connection.""" +type TransactionEdge { + """A cursor for use in pagination""" + cursor: String! + + """The item at the end of the edge""" + node: Transaction! +} + +enum TxDirection { + RECEIVE + SEND +} + +enum TxNotificationType { + IntraLedgerPayment + IntraLedgerReceipt + LigtningReceipt + OnchainPayment + OnchainReceipt + OnchainReceiptPending +} + +enum TxStatus { + FAILURE + PENDING + SUCCESS +} + +type UpgradePayload { + authToken: AuthToken + errors: [Error!]! + success: Boolean! +} + +""" +A wallet belonging to an account which contains a USD balance and a list of transactions. +""" +type UsdWallet implements Wallet { + accountId: ID! + balance: SignedAmount! + id: ID! + invoiceByPaymentHash(paymentHash: PaymentHash!): Invoice! + + """A list of all invoices associated with walletIds optionally passed.""" + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): InvoiceConnection + + """An unconfirmed incoming onchain balance.""" + pendingIncomingBalance: SignedAmount! + pendingIncomingTransactions: [Transaction!]! + pendingIncomingTransactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + ): [Transaction!]! + transactionById(transactionId: ID!): Transaction! + transactions( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): TransactionConnection + transactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): TransactionConnection + transactionsByPaymentHash(paymentHash: PaymentHash!): [Transaction!]! + walletCurrency: WalletCurrency! +} + +type User { + """ + Get single contact details. + Can include the transactions associated with the contact. + """ + contactByUsername(username: Username!): UserContact! @deprecated(reason: "will be moved to Accounts") + + """ + Get full list of contacts. + Can include the transactions associated with each contact. + """ + contacts: [UserContact!]! @deprecated(reason: "will be moved to account") + createdAt: Timestamp! + defaultAccount: Account! + + """Email address""" + email: Email + id: ID! + + """ + Preferred language for user. + When value is 'default' the intent is to use preferred language from OS settings. + """ + language: Language! + + """Phone number with international calling code.""" + phone: Phone + + """Whether TOTP is enabled for this user.""" + totpEnabled: Boolean! + + """Optional immutable user friendly identifier.""" + username: Username @deprecated(reason: "will be moved to @Handle in Account and Wallet") +} + +type UserContact { + """ + Alias the user can set for this contact. + Only the user can see the alias attached to their contact. + """ + alias: ContactAlias + id: Username! + + """Paginated list of transactions sent to/from this contact.""" + transactions( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): TransactionConnection + transactionsCount: Int! + + """Actual identifier of the contact.""" + username: Username! +} + +input UserContactUpdateAliasInput { + alias: ContactAlias! + username: Username! +} + +type UserContactUpdateAliasPayload { + contact: UserContact + errors: [Error!]! +} + +type UserEmailDeletePayload { + errors: [Error!]! + me: User +} + +input UserEmailRegistrationInitiateInput { + email: EmailAddress! +} + +type UserEmailRegistrationInitiatePayload { + emailRegistrationId: EmailRegistrationId + errors: [Error!]! + me: User +} + +input UserEmailRegistrationValidateInput { + code: OneTimeAuthCode! + emailRegistrationId: EmailRegistrationId! +} + +type UserEmailRegistrationValidatePayload { + errors: [Error!]! + me: User +} + +input UserLoginInput { + code: OneTimeAuthCode! + phone: Phone! +} + +input UserLoginUpgradeInput { + code: OneTimeAuthCode! + phone: Phone! +} + +input UserLogoutInput { + deviceToken: String! +} + +type UserPhoneDeletePayload { + errors: [Error!]! + me: User +} + +input UserPhoneRegistrationInitiateInput { + channel: PhoneCodeChannelType + phone: Phone! +} + +input UserPhoneRegistrationValidateInput { + code: OneTimeAuthCode! + phone: Phone! +} + +type UserPhoneRegistrationValidatePayload { + errors: [Error!]! + me: User +} + +type UserTotpDeletePayload { + errors: [Error!]! + me: User +} + +type UserTotpRegistrationInitiatePayload { + errors: [Error!]! + totpRegistrationId: TotpRegistrationId + totpSecret: TotpSecret +} + +input UserTotpRegistrationValidateInput { + authToken: AuthToken + totpCode: TotpCode! + totpRegistrationId: TotpRegistrationId! +} + +type UserTotpRegistrationValidatePayload { + errors: [Error!]! + me: User +} + +union UserUpdate = IntraLedgerUpdate | LnUpdate | OnChainUpdate | Price | RealtimePrice + +input UserUpdateLanguageInput { + language: Language! +} + +type UserUpdateLanguagePayload { + errors: [Error!]! + user: User +} + +input UserUpdateUsernameInput { + username: Username! +} + +type UserUpdateUsernamePayload { + errors: [Error!]! + user: User +} + +"""Unique identifier of a user""" +scalar Username + +""" +A generic wallet which stores value in one of our supported currencies. +""" +interface Wallet { + accountId: ID! + balance: SignedAmount! + id: ID! + invoiceByPaymentHash( + """ + The lightning invoice with the matching paymentHash belonging to this wallet. + """ + paymentHash: PaymentHash! + ): Invoice! + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): InvoiceConnection + pendingIncomingBalance: SignedAmount! + + """ + Pending incoming OnChain transactions. When transactions + are confirmed they will receive a new id and be found in the transactions + list. Transactions are ordered anti-chronologically, + ie: the newest transaction will be first + """ + pendingIncomingTransactions: [Transaction!]! + + """ + Pending incoming OnChain transactions. When transactions + are confirmed they will receive a new id and be found in the transactions + list. Transactions are ordered anti-chronologically, + ie: the newest transaction will be first + """ + pendingIncomingTransactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + ): [Transaction!]! + transactionById(transactionId: ID!): Transaction! + + """ + Transactions are ordered anti-chronologically, + ie: the newest transaction will be first + """ + transactions( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): TransactionConnection + + """ + Transactions are ordered anti-chronologically, + ie: the newest transaction will be first + """ + transactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): TransactionConnection + + """ + Returns the transactions that include this paymentHash. This should be a list of size one for a received lightning payment. This can be more that one transaction for a sent lightning payment. + """ + transactionsByPaymentHash( + """The payment hash of the lightning invoice paid in this transaction.""" + paymentHash: PaymentHash! + ): [Transaction!]! + walletCurrency: WalletCurrency! +} + +enum WalletCurrency { + BTC + USD +} + +"""Unique identifier of a wallet""" +scalar WalletId diff --git a/charts/galoy/apollo-router/supergraph.graphql b/charts/galoy/apollo-router/supergraph.graphql index ed23e006ea..bcb5800a00 100644 --- a/charts/galoy/apollo-router/supergraph.graphql +++ b/charts/galoy/apollo-router/supergraph.graphql @@ -26,12 +26,28 @@ interface Account { callbackEndpoints: [CallbackEndpoint!]! csvTransactions(walletIds: [WalletId!]!): String! - defaultWalletId: WalletId! + defaultWallet: PublicWallet! + defaultWalletId: WalletId! @deprecated(reason: "Shifting property to 'defaultWallet.id'") displayCurrency: DisplayCurrency! id: ID! + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + walletIds: [WalletId] + ): InvoiceConnection level: AccountLevel! limits: AccountLimits! notificationSettings: NotificationSettings! + pendingIncomingTransactions(walletIds: [WalletId]): [Transaction!]! realtimePrice: RealtimePrice! transactions( """Returns the items in the list that come after the specified cursor.""" @@ -47,6 +63,7 @@ interface Account last: Int walletIds: [WalletId] ): TransactionConnection + walletById(walletId: WalletId!): Wallet! wallets: [Wallet!]! } @@ -154,6 +171,46 @@ type AccountUpdateNotificationSettingsPayload errors: [Error!]! } +type ApiKey + @join__type(graph: API_KEYS) +{ + id: ID! + name: String! + createdAt: Timestamp! + revoked: Boolean! + expired: Boolean! + lastUsedAt: Timestamp + expiresAt: Timestamp + readOnly: Boolean! +} + +input ApiKeyCreateInput + @join__type(graph: API_KEYS) +{ + name: String! + expireInDays: Int + readOnly: Boolean! = false +} + +type ApiKeyCreatePayload + @join__type(graph: API_KEYS) +{ + apiKey: ApiKey! + apiKeySecret: String! +} + +input ApiKeyRevokeInput + @join__type(graph: API_KEYS) +{ + id: ID! +} + +type ApiKeyRevokePayload + @join__type(graph: API_KEYS) +{ + apiKey: ApiKey! +} + """An Opaque Bearer token""" scalar AuthToken @join__type(graph: PUBLIC) @@ -178,9 +235,31 @@ type BTCWallet implements Wallet """A balance stored in BTC.""" balance: SignedAmount! id: ID! + invoiceByPaymentHash(paymentHash: PaymentHash!): Invoice! + + """A list of all invoices associated with walletIds optionally passed.""" + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): InvoiceConnection """An unconfirmed incoming onchain balance.""" pendingIncomingBalance: SignedAmount! + pendingIncomingTransactions: [Transaction!]! + pendingIncomingTransactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + ): [Transaction!]! + transactionById(transactionId: ID!): Transaction! """A list of BTC transactions associated with this wallet.""" transactions( @@ -212,6 +291,7 @@ type BTCWallet implements Wallet """Returns the last n items from the list.""" last: Int ): TransactionConnection + transactionsByPaymentHash(paymentHash: PaymentHash!): [Transaction!]! walletCurrency: WalletCurrency! } @@ -296,12 +376,30 @@ type ConsumerAccount implements Account return CSV stream, base64 encoded, of the list of transactions in the wallet """ csvTransactions(walletIds: [WalletId!]!): String! + defaultWallet: PublicWallet! defaultWalletId: WalletId! displayCurrency: DisplayCurrency! id: ID! + + """A list of all invoices associated with walletIds optionally passed.""" + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + walletIds: [WalletId] + ): InvoiceConnection level: AccountLevel! limits: AccountLimits! notificationSettings: NotificationSettings! + pendingIncomingTransactions(walletIds: [WalletId]): [Transaction!]! """List the quiz questions of the consumer account""" quiz: [Quiz!]! @@ -324,6 +422,7 @@ type ConsumerAccount implements Account last: Int walletIds: [WalletId] ): TransactionConnection + walletById(walletId: WalletId!): Wallet! wallets: [Wallet!]! } @@ -499,6 +598,9 @@ type InitiationViaLn @join__type(graph: PUBLIC) { paymentHash: PaymentHash! + + """Bolt11 invoice""" + paymentRequest: LnPaymentRequest! } type InitiationViaOnChain @@ -524,11 +626,12 @@ input IntraLedgerPaymentSendInput type IntraLedgerUpdate @join__type(graph: PUBLIC) { - amount: SatAmount! - displayCurrencyPerSat: Float! + amount: SatAmount! @deprecated(reason: "Deprecated in favor of transaction") + displayCurrencyPerSat: Float! @deprecated(reason: "Deprecated in favor of transaction") + transaction: Transaction! txNotificationType: TxNotificationType! usdPerSat: Float! @deprecated(reason: "updated over displayCurrencyPerSat") - walletId: WalletId! + walletId: WalletId! @deprecated(reason: "Deprecated in favor of transaction") } input IntraLedgerUsdPaymentSendInput @@ -545,6 +648,49 @@ input IntraLedgerUsdPaymentSendInput walletId: WalletId! } +"""A lightning invoice.""" +interface Invoice + @join__type(graph: PUBLIC) +{ + createdAt: Timestamp! + + """The payment hash of the lightning invoice.""" + paymentHash: PaymentHash! + + """The bolt11 invoice to be paid.""" + paymentRequest: LnPaymentRequest! + + """ + The payment secret of the lightning invoice. This is not the preimage of the payment hash. + """ + paymentSecret: LnPaymentSecret! + + """The payment status of the invoice.""" + paymentStatus: InvoicePaymentStatus! +} + +"""A connection to a list of items.""" +type InvoiceConnection + @join__type(graph: PUBLIC) +{ + """A list of edges.""" + edges: [InvoiceEdge!] + + """Information to aid in pagination.""" + pageInfo: PageInfo! +} + +"""An edge in a connection.""" +type InvoiceEdge + @join__type(graph: PUBLIC) +{ + """A cursor for use in pagination""" + cursor: String! + + """The item at the end of the edge""" + node: Invoice! +} + enum InvoicePaymentStatus @join__type(graph: PUBLIC) { @@ -556,6 +702,7 @@ enum InvoicePaymentStatus scalar join__FieldSet enum join__Graph { + API_KEYS @join__graph(name: "api_keys", url: "http://bats-tests:5397/graphql") PUBLIC @join__graph(name: "public", url: "http://bats-tests:4012/graphql") } @@ -576,13 +723,29 @@ enum link__Purpose { EXECUTION } -type LnInvoice +input LnAddressPaymentSendInput + @join__type(graph: PUBLIC) +{ + """Amount in satoshis.""" + amount: SatAmount! + + """Lightning address to send to.""" + lnAddress: String! + + """Wallet ID to send bitcoin from.""" + walletId: WalletId! +} + +type LnInvoice implements Invoice + @join__implements(graph: PUBLIC, interface: "Invoice") @join__type(graph: PUBLIC) { + createdAt: Timestamp! paymentHash: PaymentHash! paymentRequest: LnPaymentRequest! paymentSecret: LnPaymentSecret! - satoshis: SatAmount + paymentStatus: InvoicePaymentStatus! + satoshis: SatAmount! } input LnInvoiceCreateInput @@ -660,12 +823,15 @@ type LnInvoicePaymentStatusPayload status: InvoicePaymentStatus } -type LnNoAmountInvoice +type LnNoAmountInvoice implements Invoice + @join__implements(graph: PUBLIC, interface: "Invoice") @join__type(graph: PUBLIC) { + createdAt: Timestamp! paymentHash: PaymentHash! paymentRequest: LnPaymentRequest! paymentSecret: LnPaymentSecret! + paymentStatus: InvoicePaymentStatus! } input LnNoAmountInvoiceCreateInput @@ -770,11 +936,44 @@ scalar LnPaymentSecret type LnUpdate @join__type(graph: PUBLIC) { - paymentHash: PaymentHash! + paymentHash: PaymentHash! @deprecated(reason: "Deprecated in favor of transaction") status: InvoicePaymentStatus! + transaction: Transaction! + walletId: WalletId! @deprecated(reason: "Deprecated in favor of transaction") +} + +input LnurlPaymentSendInput + @join__type(graph: PUBLIC) +{ + """Amount in satoshis.""" + amount: SatAmount! + + """Lnurl string to send to.""" + lnurl: String! + + """Wallet ID to send bitcoin from.""" walletId: WalletId! } +input LnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipientInput + @join__type(graph: PUBLIC) +{ + """Amount in satoshis.""" + amount: SatAmount! + descriptionHash: Hex32Bytes + + """Optional invoice expiration time in minutes.""" + expiresIn: Minutes + + """ + Optional memo for the lightning invoice. Acts as a note to the recipient. + """ + memo: Memo + + """Wallet ID for a USD wallet which belongs to the account of any user.""" + recipientWalletId: WalletId! +} + input LnUsdInvoiceCreateInput @join__type(graph: PUBLIC) { @@ -848,87 +1047,101 @@ type MobileVersions } type Mutation - @join__type(graph: PUBLIC) -{ - accountDelete: AccountDeletePayload! - accountDisableNotificationCategory(input: AccountDisableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! - accountDisableNotificationChannel(input: AccountDisableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! - accountEnableNotificationCategory(input: AccountEnableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! - accountEnableNotificationChannel(input: AccountEnableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! - accountUpdateDefaultWalletId(input: AccountUpdateDefaultWalletIdInput!): AccountUpdateDefaultWalletIdPayload! - accountUpdateDisplayCurrency(input: AccountUpdateDisplayCurrencyInput!): AccountUpdateDisplayCurrencyPayload! - callbackEndpointAdd(input: CallbackEndpointAddInput!): CallbackEndpointAddPayload! - callbackEndpointDelete(input: CallbackEndpointDeleteInput!): SuccessPayload! - captchaCreateChallenge: CaptchaCreateChallengePayload! - captchaRequestAuthCode(input: CaptchaRequestAuthCodeInput!): SuccessPayload! - deviceNotificationTokenCreate(input: DeviceNotificationTokenCreateInput!): SuccessPayload! - feedbackSubmit(input: FeedbackSubmitInput!): SuccessPayload! + @join__type(graph: API_KEYS) + @join__type(graph: PUBLIC) +{ + apiKeyCreate(input: ApiKeyCreateInput!): ApiKeyCreatePayload! @join__field(graph: API_KEYS) + apiKeyRevoke(input: ApiKeyRevokeInput!): ApiKeyRevokePayload! @join__field(graph: API_KEYS) + accountDelete: AccountDeletePayload! @join__field(graph: PUBLIC) + accountDisableNotificationCategory(input: AccountDisableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: PUBLIC) + accountDisableNotificationChannel(input: AccountDisableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: PUBLIC) + accountEnableNotificationCategory(input: AccountEnableNotificationCategoryInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: PUBLIC) + accountEnableNotificationChannel(input: AccountEnableNotificationChannelInput!): AccountUpdateNotificationSettingsPayload! @join__field(graph: PUBLIC) + accountUpdateDefaultWalletId(input: AccountUpdateDefaultWalletIdInput!): AccountUpdateDefaultWalletIdPayload! @join__field(graph: PUBLIC) + accountUpdateDisplayCurrency(input: AccountUpdateDisplayCurrencyInput!): AccountUpdateDisplayCurrencyPayload! @join__field(graph: PUBLIC) + callbackEndpointAdd(input: CallbackEndpointAddInput!): CallbackEndpointAddPayload! @join__field(graph: PUBLIC) + callbackEndpointDelete(input: CallbackEndpointDeleteInput!): SuccessPayload! @join__field(graph: PUBLIC) + captchaCreateChallenge: CaptchaCreateChallengePayload! @join__field(graph: PUBLIC) + captchaRequestAuthCode(input: CaptchaRequestAuthCodeInput!): SuccessPayload! @join__field(graph: PUBLIC) + deviceNotificationTokenCreate(input: DeviceNotificationTokenCreateInput!): SuccessPayload! @join__field(graph: PUBLIC) + feedbackSubmit(input: FeedbackSubmitInput!): SuccessPayload! @join__field(graph: PUBLIC) """ Actions a payment which is internal to the ledger e.g. it does not use onchain/lightning. Returns payment status (success, failed, pending, already_paid). """ - intraLedgerPaymentSend(input: IntraLedgerPaymentSendInput!): PaymentSendPayload! + intraLedgerPaymentSend(input: IntraLedgerPaymentSendInput!): PaymentSendPayload! @join__field(graph: PUBLIC) """ Actions a payment which is internal to the ledger e.g. it does not use onchain/lightning. Returns payment status (success, failed, pending, already_paid). """ - intraLedgerUsdPaymentSend(input: IntraLedgerUsdPaymentSendInput!): PaymentSendPayload! + intraLedgerUsdPaymentSend(input: IntraLedgerUsdPaymentSendInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + + """Sends a payment to a lightning address.""" + lnAddressPaymentSend(input: LnAddressPaymentSendInput!): PaymentSendPayload! @join__field(graph: PUBLIC) """ Returns a lightning invoice for an associated wallet. When invoice is paid the value will be credited to a BTC wallet. Expires after 'expiresIn' or 24 hours. """ - lnInvoiceCreate(input: LnInvoiceCreateInput!): LnInvoicePayload! + lnInvoiceCreate(input: LnInvoiceCreateInput!): LnInvoicePayload! @join__field(graph: PUBLIC) """ Returns a lightning invoice for an associated wallet. When invoice is paid the value will be credited to a BTC wallet. Expires after 'expiresIn' or 24 hours. """ - lnInvoiceCreateOnBehalfOfRecipient(input: LnInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! - lnInvoiceFeeProbe(input: LnInvoiceFeeProbeInput!): SatAmountPayload! + lnInvoiceCreateOnBehalfOfRecipient(input: LnInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! @join__field(graph: PUBLIC) + lnInvoiceFeeProbe(input: LnInvoiceFeeProbeInput!): SatAmountPayload! @join__field(graph: PUBLIC) """ Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. Provided wallet can be USD or BTC and must have sufficient balance to cover amount in lightning invoice. Returns payment status (success, failed, pending, already_paid). """ - lnInvoicePaymentSend(input: LnInvoicePaymentInput!): PaymentSendPayload! + lnInvoicePaymentSend(input: LnInvoicePaymentInput!): PaymentSendPayload! @join__field(graph: PUBLIC) """ Returns a lightning invoice for an associated wallet. Can be used to receive any supported currency value (currently USD or BTC). Expires after 'expiresIn' or 24 hours for BTC invoices or 5 minutes for USD invoices. """ - lnNoAmountInvoiceCreate(input: LnNoAmountInvoiceCreateInput!): LnNoAmountInvoicePayload! + lnNoAmountInvoiceCreate(input: LnNoAmountInvoiceCreateInput!): LnNoAmountInvoicePayload! @join__field(graph: PUBLIC) """ Returns a lightning invoice for an associated wallet. Can be used to receive any supported currency value (currently USD or BTC). Expires after 'expiresIn' or 24 hours for BTC invoices or 5 minutes for USD invoices. """ - lnNoAmountInvoiceCreateOnBehalfOfRecipient(input: LnNoAmountInvoiceCreateOnBehalfOfRecipientInput!): LnNoAmountInvoicePayload! - lnNoAmountInvoiceFeeProbe(input: LnNoAmountInvoiceFeeProbeInput!): SatAmountPayload! + lnNoAmountInvoiceCreateOnBehalfOfRecipient(input: LnNoAmountInvoiceCreateOnBehalfOfRecipientInput!): LnNoAmountInvoicePayload! @join__field(graph: PUBLIC) + lnNoAmountInvoiceFeeProbe(input: LnNoAmountInvoiceFeeProbeInput!): SatAmountPayload! @join__field(graph: PUBLIC) """ Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. Provided wallet must be BTC and must have sufficient balance to cover amount specified in mutation request. Returns payment status (success, failed, pending, already_paid). """ - lnNoAmountInvoicePaymentSend(input: LnNoAmountInvoicePaymentInput!): PaymentSendPayload! - lnNoAmountUsdInvoiceFeeProbe(input: LnNoAmountUsdInvoiceFeeProbeInput!): CentAmountPayload! + lnNoAmountInvoicePaymentSend(input: LnNoAmountInvoicePaymentInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + lnNoAmountUsdInvoiceFeeProbe(input: LnNoAmountUsdInvoiceFeeProbeInput!): CentAmountPayload! @join__field(graph: PUBLIC) """ Pay a lightning invoice using a balance from a wallet which is owned by the account of the current user. Provided wallet must be USD and have sufficient balance to cover amount specified in mutation request. Returns payment status (success, failed, pending, already_paid). """ - lnNoAmountUsdInvoicePaymentSend(input: LnNoAmountUsdInvoicePaymentInput!): PaymentSendPayload! + lnNoAmountUsdInvoicePaymentSend(input: LnNoAmountUsdInvoicePaymentInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + + """ + Returns a lightning invoice denominated in satoshis for an associated wallet. + When invoice is paid the equivalent value at invoice creation will be credited to a USD wallet. + Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate + associated with the amount). + """ + lnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipient(input: LnUsdInvoiceBtcDenominatedCreateOnBehalfOfRecipientInput!): LnInvoicePayload! @join__field(graph: PUBLIC) """ Returns a lightning invoice denominated in satoshis for an associated wallet. @@ -936,7 +1149,7 @@ type Mutation Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate associated with the amount). """ - lnUsdInvoiceCreate(input: LnUsdInvoiceCreateInput!): LnInvoicePayload! + lnUsdInvoiceCreate(input: LnUsdInvoiceCreateInput!): LnInvoicePayload! @join__field(graph: PUBLIC) """ Returns a lightning invoice denominated in satoshis for an associated wallet. @@ -944,31 +1157,34 @@ type Mutation Expires after 'expiresIn' or 5 minutes (short expiry time because there is a USD/BTC exchange rate associated with the amount). """ - lnUsdInvoiceCreateOnBehalfOfRecipient(input: LnUsdInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! - lnUsdInvoiceFeeProbe(input: LnUsdInvoiceFeeProbeInput!): SatAmountPayload! - onChainAddressCreate(input: OnChainAddressCreateInput!): OnChainAddressPayload! - onChainAddressCurrent(input: OnChainAddressCurrentInput!): OnChainAddressPayload! - onChainPaymentSend(input: OnChainPaymentSendInput!): PaymentSendPayload! - onChainPaymentSendAll(input: OnChainPaymentSendAllInput!): PaymentSendPayload! - onChainUsdPaymentSend(input: OnChainUsdPaymentSendInput!): PaymentSendPayload! - onChainUsdPaymentSendAsBtcDenominated(input: OnChainUsdPaymentSendAsBtcDenominatedInput!): PaymentSendPayload! - quizCompleted(input: QuizCompletedInput!): QuizCompletedPayload! - userContactUpdateAlias(input: UserContactUpdateAliasInput!): UserContactUpdateAliasPayload! @deprecated(reason: "will be moved to AccountContact") - userEmailDelete: UserEmailDeletePayload! - userEmailRegistrationInitiate(input: UserEmailRegistrationInitiateInput!): UserEmailRegistrationInitiatePayload! - userEmailRegistrationValidate(input: UserEmailRegistrationValidateInput!): UserEmailRegistrationValidatePayload! - userLogin(input: UserLoginInput!): AuthTokenPayload! - userLoginUpgrade(input: UserLoginUpgradeInput!): UpgradePayload! - userLogout(input: UserLogoutInput): SuccessPayload! - userPhoneDelete: UserPhoneDeletePayload! - userPhoneRegistrationInitiate(input: UserPhoneRegistrationInitiateInput!): SuccessPayload! - userPhoneRegistrationValidate(input: UserPhoneRegistrationValidateInput!): UserPhoneRegistrationValidatePayload! - userQuizQuestionUpdateCompleted(input: UserQuizQuestionUpdateCompletedInput!): UserQuizQuestionUpdateCompletedPayload! @deprecated(reason: "Use QuizCompletedMutation instead") - userTotpDelete(input: UserTotpDeleteInput!): UserTotpDeletePayload! - userTotpRegistrationInitiate(input: UserTotpRegistrationInitiateInput!): UserTotpRegistrationInitiatePayload! - userTotpRegistrationValidate(input: UserTotpRegistrationValidateInput!): UserTotpRegistrationValidatePayload! - userUpdateLanguage(input: UserUpdateLanguageInput!): UserUpdateLanguagePayload! - userUpdateUsername(input: UserUpdateUsernameInput!): UserUpdateUsernamePayload! @deprecated(reason: "Username will be moved to @Handle in Accounts. Also SetUsername naming should be used instead of UpdateUsername to reflect the idempotency of Handles") + lnUsdInvoiceCreateOnBehalfOfRecipient(input: LnUsdInvoiceCreateOnBehalfOfRecipientInput!): LnInvoicePayload! @join__field(graph: PUBLIC) + lnUsdInvoiceFeeProbe(input: LnUsdInvoiceFeeProbeInput!): SatAmountPayload! @join__field(graph: PUBLIC) + + """Sends a payment to a lightning address.""" + lnurlPaymentSend(input: LnurlPaymentSendInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + onChainAddressCreate(input: OnChainAddressCreateInput!): OnChainAddressPayload! @join__field(graph: PUBLIC) + onChainAddressCurrent(input: OnChainAddressCurrentInput!): OnChainAddressPayload! @join__field(graph: PUBLIC) + onChainPaymentSend(input: OnChainPaymentSendInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + onChainPaymentSendAll(input: OnChainPaymentSendAllInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + onChainUsdPaymentSend(input: OnChainUsdPaymentSendInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + onChainUsdPaymentSendAsBtcDenominated(input: OnChainUsdPaymentSendAsBtcDenominatedInput!): PaymentSendPayload! @join__field(graph: PUBLIC) + quizClaim(input: QuizClaimInput!): QuizClaimPayload! @join__field(graph: PUBLIC) + quizCompleted(input: QuizCompletedInput!): QuizCompletedPayload! @join__field(graph: PUBLIC) @deprecated(reason: "Use quizClaim instead") + userContactUpdateAlias(input: UserContactUpdateAliasInput!): UserContactUpdateAliasPayload! @join__field(graph: PUBLIC) @deprecated(reason: "will be moved to AccountContact") + userEmailDelete: UserEmailDeletePayload! @join__field(graph: PUBLIC) + userEmailRegistrationInitiate(input: UserEmailRegistrationInitiateInput!): UserEmailRegistrationInitiatePayload! @join__field(graph: PUBLIC) + userEmailRegistrationValidate(input: UserEmailRegistrationValidateInput!): UserEmailRegistrationValidatePayload! @join__field(graph: PUBLIC) + userLogin(input: UserLoginInput!): AuthTokenPayload! @join__field(graph: PUBLIC) + userLoginUpgrade(input: UserLoginUpgradeInput!): UpgradePayload! @join__field(graph: PUBLIC) + userLogout(input: UserLogoutInput): SuccessPayload! @join__field(graph: PUBLIC) + userPhoneDelete: UserPhoneDeletePayload! @join__field(graph: PUBLIC) + userPhoneRegistrationInitiate(input: UserPhoneRegistrationInitiateInput!): SuccessPayload! @join__field(graph: PUBLIC) + userPhoneRegistrationValidate(input: UserPhoneRegistrationValidateInput!): UserPhoneRegistrationValidatePayload! @join__field(graph: PUBLIC) + userTotpDelete: UserTotpDeletePayload! @join__field(graph: PUBLIC) + userTotpRegistrationInitiate: UserTotpRegistrationInitiatePayload! @join__field(graph: PUBLIC) + userTotpRegistrationValidate(input: UserTotpRegistrationValidateInput!): UserTotpRegistrationValidatePayload! @join__field(graph: PUBLIC) + userUpdateLanguage(input: UserUpdateLanguageInput!): UserUpdateLanguagePayload! @join__field(graph: PUBLIC) + userUpdateUsername(input: UserUpdateUsernameInput!): UserUpdateUsernamePayload! @join__field(graph: PUBLIC) @deprecated(reason: "Username will be moved to @Handle in Accounts. Also SetUsername naming should be used instead of UpdateUsername to reflect the idempotency of Handles") } type MyUpdatesPayload @@ -1038,7 +1254,7 @@ input OnChainPaymentSendAllInput { address: OnChainAddress! memo: Memo - speed: PayoutSpeed = FAST + speed: PayoutSpeed! = FAST walletId: WalletId! } @@ -1048,7 +1264,7 @@ input OnChainPaymentSendInput address: OnChainAddress! amount: SatAmount! memo: Memo - speed: PayoutSpeed = FAST + speed: PayoutSpeed! = FAST walletId: WalletId! } @@ -1064,12 +1280,13 @@ scalar OnChainTxHash type OnChainUpdate @join__type(graph: PUBLIC) { - amount: SatAmount! - displayCurrencyPerSat: Float! - txHash: OnChainTxHash! + amount: SatAmount! @deprecated(reason: "Deprecated in favor of transaction") + displayCurrencyPerSat: Float! @deprecated(reason: "Deprecated in favor of transaction") + transaction: Transaction! + txHash: OnChainTxHash! @deprecated(reason: "Deprecated in favor of transaction") txNotificationType: TxNotificationType! usdPerSat: Float! @deprecated(reason: "updated over displayCurrencyPerSat") - walletId: WalletId! + walletId: WalletId! @deprecated(reason: "Deprecated in favor of transaction") } input OnChainUsdPaymentSendAsBtcDenominatedInput @@ -1078,7 +1295,7 @@ input OnChainUsdPaymentSendAsBtcDenominatedInput address: OnChainAddress! amount: SatAmount! memo: Memo - speed: PayoutSpeed = FAST + speed: PayoutSpeed! = FAST walletId: WalletId! } @@ -1088,7 +1305,7 @@ input OnChainUsdPaymentSendInput address: OnChainAddress! amount: CentAmount! memo: Memo - speed: PayoutSpeed = FAST + speed: PayoutSpeed! = FAST walletId: WalletId! } @@ -1145,6 +1362,7 @@ type PaymentSendPayload { errors: [Error!]! status: PaymentSendResult + transaction: Transaction } enum PaymentSendResult @@ -1271,31 +1489,31 @@ A public view of a generic wallet which stores value in one of our supported cur type PublicWallet @join__type(graph: PUBLIC) { + currency: WalletCurrency! id: ID! - walletCurrency: WalletCurrency! + walletCurrency: WalletCurrency! @deprecated(reason: "Shifting property to 'currency'") } type Query + @join__type(graph: API_KEYS) @join__type(graph: PUBLIC) { - accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! - btcPrice(currency: DisplayCurrency! = "USD"): Price @deprecated(reason: "Deprecated in favor of realtimePrice") - btcPriceList(range: PriceGraphRange!): [PricePoint] - businessMapMarkers: [MapMarker] - currencyList: [Currency!]! - globals: Globals - lnInvoicePaymentStatus(input: LnInvoicePaymentStatusInput!): LnInvoicePaymentStatusPayload! - me: User - mobileVersions: [MobileVersions] - onChainTxFee(address: OnChainAddress!, amount: SatAmount!, speed: PayoutSpeed = FAST, walletId: WalletId!): OnChainTxFee! - onChainUsdTxFee(address: OnChainAddress!, amount: CentAmount!, speed: PayoutSpeed = FAST, walletId: WalletId!): OnChainUsdTxFee! - onChainUsdTxFeeAsBtcDenominated(address: OnChainAddress!, amount: SatAmount!, speed: PayoutSpeed = FAST, walletId: WalletId!): OnChainUsdTxFee! - quizQuestions: [QuizQuestion] @deprecated(reason: "TODO: remove. we don't need a non authenticated version of this query. the users can only do the query while authenticated") + accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: PUBLIC) + btcPriceList(range: PriceGraphRange!): [PricePoint] @join__field(graph: PUBLIC) + businessMapMarkers: [MapMarker] @join__field(graph: PUBLIC) + currencyList: [Currency!]! @join__field(graph: PUBLIC) + globals: Globals @join__field(graph: PUBLIC) + lnInvoicePaymentStatus(input: LnInvoicePaymentStatusInput!): LnInvoicePaymentStatusPayload! @join__field(graph: PUBLIC) + me: User @join__field(graph: PUBLIC) + mobileVersions: [MobileVersions] @join__field(graph: PUBLIC) + onChainTxFee(address: OnChainAddress!, amount: SatAmount!, speed: PayoutSpeed! = FAST, walletId: WalletId!): OnChainTxFee! @join__field(graph: PUBLIC) + onChainUsdTxFee(address: OnChainAddress!, amount: CentAmount!, speed: PayoutSpeed! = FAST, walletId: WalletId!): OnChainUsdTxFee! @join__field(graph: PUBLIC) + onChainUsdTxFeeAsBtcDenominated(address: OnChainAddress!, amount: SatAmount!, speed: PayoutSpeed! = FAST, walletId: WalletId!): OnChainUsdTxFee! @join__field(graph: PUBLIC) """Returns 1 Sat and 1 Usd Cent price for the given currency""" - realtimePrice(currency: DisplayCurrency = "USD"): RealtimePrice! - userDefaultWalletId(username: Username!): WalletId! @deprecated(reason: "will be migrated to AccountDefaultWalletId") - usernameAvailable(username: Username!): Boolean + realtimePrice(currency: DisplayCurrency = "USD"): RealtimePrice! @join__field(graph: PUBLIC) + userDefaultWalletId(username: Username!): WalletId! @join__field(graph: PUBLIC) @deprecated(reason: "will be migrated to AccountDefaultWalletId") + usernameAvailable(username: Username!): Boolean @join__field(graph: PUBLIC) } type Quiz @@ -1305,29 +1523,35 @@ type Quiz amount: SatAmount! completed: Boolean! id: ID! + notBefore: Timestamp } -input QuizCompletedInput +input QuizClaimInput @join__type(graph: PUBLIC) { id: ID! } -type QuizCompletedPayload +type QuizClaimPayload @join__type(graph: PUBLIC) { errors: [Error!]! - quiz: Quiz + quizzes: [Quiz!]! } -type QuizQuestion +input QuizCompletedInput @join__type(graph: PUBLIC) { - """The earn reward in Satoshis for the quiz question""" - earnAmount: SatAmount! id: ID! } +type QuizCompletedPayload + @join__type(graph: PUBLIC) +{ + errors: [Error!]! + quiz: Quiz +} + type RealtimePrice @join__type(graph: PUBLIC) { @@ -1403,6 +1627,7 @@ type SettlementViaLn type SettlementViaOnChain @join__type(graph: PUBLIC) { + arrivalInMempoolEstimatedAt: Timestamp transactionHash: OnChainTxHash vout: Int } @@ -1439,6 +1664,7 @@ type SuccessPayload Timestamp field, serialized as Unix time (the number of seconds since the Unix epoch) """ scalar Timestamp + @join__type(graph: API_KEYS) @join__type(graph: PUBLIC) """A time-based one-time password""" @@ -1523,7 +1749,7 @@ enum TxNotificationType { IntraLedgerPayment @join__enumValue(graph: PUBLIC) IntraLedgerReceipt @join__enumValue(graph: PUBLIC) - LnInvoicePaid @join__enumValue(graph: PUBLIC) + LigtningReceipt @join__enumValue(graph: PUBLIC) OnchainPayment @join__enumValue(graph: PUBLIC) OnchainReceipt @join__enumValue(graph: PUBLIC) OnchainReceiptPending @join__enumValue(graph: PUBLIC) @@ -1555,9 +1781,31 @@ type UsdWallet implements Wallet accountId: ID! balance: SignedAmount! id: ID! + invoiceByPaymentHash(paymentHash: PaymentHash!): Invoice! + + """A list of all invoices associated with walletIds optionally passed.""" + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): InvoiceConnection """An unconfirmed incoming onchain balance.""" pendingIncomingBalance: SignedAmount! + pendingIncomingTransactions: [Transaction!]! + pendingIncomingTransactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + ): [Transaction!]! + transactionById(transactionId: ID!): Transaction! transactions( """Returns the items in the list that come after the specified cursor.""" after: String @@ -1587,47 +1835,48 @@ type UsdWallet implements Wallet """Returns the last n items from the list.""" last: Int ): TransactionConnection + transactionsByPaymentHash(paymentHash: PaymentHash!): [Transaction!]! walletCurrency: WalletCurrency! } type User + @join__type(graph: API_KEYS, key: "id", extension: true) @join__type(graph: PUBLIC) { + id: ID! + apiKeys: [ApiKey!]! @join__field(graph: API_KEYS) + """ Get single contact details. Can include the transactions associated with the contact. """ - contactByUsername(username: Username!): UserContact! @deprecated(reason: "will be moved to Accounts") + contactByUsername(username: Username!): UserContact! @join__field(graph: PUBLIC) @deprecated(reason: "will be moved to Accounts") """ Get full list of contacts. Can include the transactions associated with each contact. """ - contacts: [UserContact!]! @deprecated(reason: "will be moved to account") - createdAt: Timestamp! - defaultAccount: Account! + contacts: [UserContact!]! @join__field(graph: PUBLIC) @deprecated(reason: "will be moved to account") + createdAt: Timestamp! @join__field(graph: PUBLIC) + defaultAccount: Account! @join__field(graph: PUBLIC) """Email address""" - email: Email - id: ID! + email: Email @join__field(graph: PUBLIC) """ Preferred language for user. When value is 'default' the intent is to use preferred language from OS settings. """ - language: Language! + language: Language! @join__field(graph: PUBLIC) """Phone number with international calling code.""" - phone: Phone - - """List the quiz questions the user may have completed.""" - quizQuestions: [UserQuizQuestion!]! @deprecated(reason: "use Quiz from Account instead") + phone: Phone @join__field(graph: PUBLIC) """Whether TOTP is enabled for this user.""" - totpEnabled: Boolean! + totpEnabled: Boolean! @join__field(graph: PUBLIC) """Optional immutable user friendly identifier.""" - username: Username @deprecated(reason: "will be moved to @Handle in Account and Wallet") + username: Username @join__field(graph: PUBLIC) @deprecated(reason: "will be moved to @Handle in Account and Wallet") } type UserContact @@ -1761,32 +2010,6 @@ type UserPhoneRegistrationValidatePayload me: User } -type UserQuizQuestion - @join__type(graph: PUBLIC) -{ - completed: Boolean! - question: QuizQuestion! -} - -input UserQuizQuestionUpdateCompletedInput - @join__type(graph: PUBLIC) -{ - id: ID! -} - -type UserQuizQuestionUpdateCompletedPayload - @join__type(graph: PUBLIC) -{ - errors: [Error!]! - userQuizQuestion: UserQuizQuestion -} - -input UserTotpDeleteInput - @join__type(graph: PUBLIC) -{ - authToken: AuthToken! -} - type UserTotpDeletePayload @join__type(graph: PUBLIC) { @@ -1794,12 +2017,6 @@ type UserTotpDeletePayload me: User } -input UserTotpRegistrationInitiateInput - @join__type(graph: PUBLIC) -{ - authToken: AuthToken! -} - type UserTotpRegistrationInitiatePayload @join__type(graph: PUBLIC) { @@ -1811,7 +2028,7 @@ type UserTotpRegistrationInitiatePayload input UserTotpRegistrationValidateInput @join__type(graph: PUBLIC) { - authToken: AuthToken! + authToken: AuthToken totpCode: TotpCode! totpRegistrationId: TotpRegistrationId! } @@ -1867,8 +2084,47 @@ interface Wallet accountId: ID! balance: SignedAmount! id: ID! + invoiceByPaymentHash( + """ + The lightning invoice with the matching paymentHash belonging to this wallet. + """ + paymentHash: PaymentHash! + ): Invoice! + invoices( + """Returns the items in the list that come after the specified cursor.""" + after: String + + """Returns the items in the list that come before the specified cursor.""" + before: String + + """Returns the first n items from the list.""" + first: Int + + """Returns the last n items from the list.""" + last: Int + ): InvoiceConnection pendingIncomingBalance: SignedAmount! + """ + Pending incoming OnChain transactions. When transactions + are confirmed they will receive a new id and be found in the transactions + list. Transactions are ordered anti-chronologically, + ie: the newest transaction will be first + """ + pendingIncomingTransactions: [Transaction!]! + + """ + Pending incoming OnChain transactions. When transactions + are confirmed they will receive a new id and be found in the transactions + list. Transactions are ordered anti-chronologically, + ie: the newest transaction will be first + """ + pendingIncomingTransactionsByAddress( + """Returns the items that include this address.""" + address: OnChainAddress! + ): [Transaction!]! + transactionById(transactionId: ID!): Transaction! + """ Transactions are ordered anti-chronologically, ie: the newest transaction will be first @@ -1907,6 +2163,14 @@ interface Wallet """Returns the last n items from the list.""" last: Int ): TransactionConnection + + """ + Returns the transactions that include this paymentHash. This should be a list of size one for a received lightning payment. This can be more that one transaction for a sent lightning payment. + """ + transactionsByPaymentHash( + """The payment hash of the lightning invoice paid in this transaction.""" + paymentHash: PaymentHash! + ): [Transaction!]! walletCurrency: WalletCurrency! } @@ -1919,4 +2183,4 @@ enum WalletCurrency """Unique identifier of a wallet""" scalar WalletId - @join__type(graph: PUBLIC) + @join__type(graph: PUBLIC) \ No newline at end of file diff --git a/charts/galoy/charts/price/templates/history-cronjob.yaml b/charts/galoy/charts/price/templates/history-cronjob.yaml index 2007c0caea..67de37a29f 100644 --- a/charts/galoy/charts/price/templates/history-cronjob.yaml +++ b/charts/galoy/charts/price/templates/history-cronjob.yaml @@ -10,6 +10,9 @@ spec: spec: activeDeadlineSeconds: 60 template: + metadata: + labels: + app: {{ include "price.history.fullname" . }}-cronjob spec: containers: - name: update-price diff --git a/charts/galoy/charts/price/templates/history-deployment.yaml b/charts/galoy/charts/price/templates/history-deployment.yaml index 1f503c26f8..9855810753 100644 --- a/charts/galoy/charts/price/templates/history-deployment.yaml +++ b/charts/galoy/charts/price/templates/history-deployment.yaml @@ -53,6 +53,10 @@ spec: secretKeyRef: name: {{ include "price.history.fullname" . }}-postgres-creds key: database + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .Values.history.tracing.otelExporterOtlpEndpoint }} + - name: OTEL_SERVICE_NAME + value: {{ .Values.history.tracing.otelServiceName }} volumeMounts: - name: custom-yaml mountPath: "/var/yaml/" diff --git a/charts/galoy/charts/price/templates/realtime-deployment.yaml b/charts/galoy/charts/price/templates/realtime-deployment.yaml index 9468f6550d..69b7352978 100644 --- a/charts/galoy/charts/price/templates/realtime-deployment.yaml +++ b/charts/galoy/charts/price/templates/realtime-deployment.yaml @@ -37,6 +37,11 @@ spec: - name: prometheus containerPort: {{ .Values.realtime.service.prometheus }} protocol: TCP + env: + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .Values.realtime.tracing.otelExporterOtlpEndpoint }} + - name: OTEL_SERVICE_NAME + value: {{ .Values.realtime.tracing.otelServiceName }} volumeMounts: - name: custom-yaml mountPath: "/var/yaml/" diff --git a/charts/galoy/charts/price/values.yaml b/charts/galoy/charts/price/values.yaml index cdeae55c9e..cdfcb3e2c7 100644 --- a/charts/galoy/charts/price/values.yaml +++ b/charts/galoy/charts/price/values.yaml @@ -32,11 +32,14 @@ nodeSelector: {} tolerations: [] affinity: {} realtime: + tracing: + otelExporterOtlpEndpoint: http://localhost:4318/v1/traces + otelServiceName: galoy-price-realtime-dev config: {} image: repository: us.gcr.io/galoy-org/price - digest: "sha256:044912ac18529955a2c37c1bc201f0ddb37b0e878f7f4d10ea084e750f00b44c" - git_ref: "53860b0" + digest: "sha256:691c94b88b57b23918edf5929c08b0eb597e2d240a950935d03f7b07b0d7c2b6" + git_ref: "8bb472c" service: type: ClusterIP prometheus: 9464 @@ -46,17 +49,20 @@ realtime: prometheus.io/port: "9464" prometheus.io/scrape: "true" history: + tracing: + otelExporterOtlpEndpoint: http://localhost:4318/v1/traces + otelServiceName: galoy-price-history-dev valuesOverride: {} image: repository: us.gcr.io/galoy-org/price-history - digest: "sha256:14ba8a6ab92f5c5c7d7682bbf93d0db5a3ad980b29c53432d4b888d223c25f3a" + digest: "sha256:13838520b7080a071b7699607f7c25cb9914f4bf0ec5e929e54c61876c1ce29c" service: type: ClusterIP prometheus: 9464 grpc: 50052 migrateImage: repository: us.gcr.io/galoy-org/price-history-migrate - digest: sha256:84c48c442ac15903f8ed3ff373ea0cccb64fe6a1d48d3fc456780217fccf85ae + digest: sha256:501fe3d5a2c71b055b142bd5c0fb1d39b2eb7abe3f03a5a2b0d38e371bfc54a4 postgresqlHost: postgresql cron: resources: {} diff --git a/charts/galoy/templates/_helpers.tpl b/charts/galoy/templates/_helpers.tpl index a4f10ca459..9bc61f10c2 100644 --- a/charts/galoy/templates/_helpers.tpl +++ b/charts/galoy/templates/_helpers.tpl @@ -46,6 +46,22 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this {{- default "trigger" .Values.galoy.trigger.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} +{{/* +Create a default fully qualified consent name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "galoy.consent.fullname" -}} +{{- default "consent" .Values.galoy.consent.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified consent name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "galoy.apiKeys.fullname" -}} +{{- default "api-keys" .Values.galoy.apiKeys.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + {{/* CronJob name */}} @@ -283,3 +299,18 @@ Return Galoy environment variables for Geetest name: {{ .Values.galoy.geetestExistingSecret.name }} key: {{ .Values.galoy.geetestExistingSecret.secret_key }} {{- end -}} + +# TODO: Remove this once https://github.com/apollographql/router/issues/4002 is resolved +# This is copied from https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_tplvalues.tpl +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} diff --git a/charts/galoy/templates/admin-ingress.yaml b/charts/galoy/templates/admin-ingress.yaml index ff548b1e5d..67e432c37c 100644 --- a/charts/galoy/templates/admin-ingress.yaml +++ b/charts/galoy/templates/admin-ingress.yaml @@ -17,11 +17,11 @@ metadata: nginx.ingress.kubernetes.io/auth-method: GET nginx.ingress.kubernetes.io/auth-response-headers: Authorization nginx.ingress.kubernetes.io/auth-snippet: | - proxy_set_header X-Original-URL $request_uri; + proxy_set_header X-Original-URL /admin$request_uri; proxy_set_header X-Forwarded-Method $request_method; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Uri $request_uri; + proxy_set_header X-Forwarded-Uri /admin$request_uri; {{- with .Values.galoy.admin.ingress.annotations }} {{- toYaml . | nindent 4 }} {{- end }} diff --git a/charts/galoy/templates/api-deployment.yaml b/charts/galoy/templates/api-deployment.yaml index 64d08fbdb2..01663eeb78 100644 --- a/charts/galoy/templates/api-deployment.yaml +++ b/charts/galoy/templates/api-deployment.yaml @@ -44,10 +44,6 @@ spec: containers: - name: api image: "{{ .Values.galoy.images.app.repository }}@{{ .Values.galoy.images.app.digest }}" - args: - - "-r" - - "/app/lib/services/tracing.js" - - "lib/servers/graphql-main-server.js" resources: {{ toYaml .Values.galoy.api.resources | nindent 10 }} ports: @@ -124,6 +120,14 @@ spec: - name: MATTERMOST_WEBHOOK_URL value: {{ .Values.galoy.mattermostWebhookUrl | quote }} + {{ if .Values.galoy.api.unsecureDefaultLoginCode.enabled }} + - name: UNSECURE_DEFAULT_LOGIN_CODE + valueFrom: + secretKeyRef: + name: {{ .Values.galoy.api.unsecureDefaultLoginCode.existingSecret.name }} + key: {{ .Values.galoy.api.unsecureDefaultLoginCode.existingSecret.key }} + {{ end }} + {{ if .Values.galoy.api.firebaseNotifications.enabled }} - name: GOOGLE_APPLICATION_CREDENTIALS value: "/tmp/firebase-service-account/service-account.json" diff --git a/charts/galoy/templates/api-ingress.yaml b/charts/galoy/templates/api-ingress.yaml index 571e8a74ff..a888791717 100644 --- a/charts/galoy/templates/api-ingress.yaml +++ b/charts/galoy/templates/api-ingress.yaml @@ -20,7 +20,7 @@ metadata: nginx.ingress.kubernetes.io/limit-connections: "80" nginx.ingress.kubernetes.io/auth-url: "http://galoy-oathkeeper-api.{{ .Release.Namespace }}.svc.cluster.local:4456/decisions" nginx.ingress.kubernetes.io/auth-method: GET - nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, Set-Cookie" + nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, Set-Cookie, X-Appcheck-Jti" nginx.ingress.kubernetes.io/auth-forward-cookie: "*" nginx.ingress.kubernetes.io/auth-snippet: | proxy_set_header X-Original-URL $request_uri; diff --git a/charts/galoy/templates/api-keys-cm.yaml b/charts/galoy/templates/api-keys-cm.yaml new file mode 100644 index 0000000000..0af1138af3 --- /dev/null +++ b/charts/galoy/templates/api-keys-cm.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "galoy.apiKeys.fullname" . }} +data: + api-keys.yml: |- + app: + key_prefix: {{ .Values.galoy.apiKeys.config.keyPrefix }} + default_expiry_days: 90 + db: + pool_size: 20 + server: + port: 5397 + jwks_url: "http://galoy-oathkeeper-api:4456/.well-known/jwks.json" + api_key_auth_header: "X-API-KEY" + tracing: + endpoint: {{ .Values.tracing.otelExporterOtlpEndpoint }} + service_name: "{{ .Values.tracing.prefix }}-{{ template "galoy.apiKeys.fullname" . }}" diff --git a/charts/galoy/templates/api-keys-deployment.yaml b/charts/galoy/templates/api-keys-deployment.yaml new file mode 100644 index 0000000000..d831aa1879 --- /dev/null +++ b/charts/galoy/templates/api-keys-deployment.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "galoy.apiKeys.fullname" . }} + labels: + app: {{ template "galoy.apiKeys.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: Helm + kube-monkey/enabled: enabled + kube-monkey/identifier: {{ template "galoy.apiKeys.fullname" . }} + kube-monkey/kill-mode: fixed + kube-monkey/kill-value: "1" + kube-monkey/mtbf: "8" +spec: + replicas: {{ .Values.galoy.apiKeys.replicas }} + selector: + matchLabels: + app: {{ template "galoy.apiKeys.fullname" . }} + template: + metadata: + name: {{ template "galoy.apiKeys.fullname" . }} + labels: + app: {{ template "galoy.apiKeys.fullname" . }} + kube-monkey/enabled: enabled + kube-monkey/identifier: {{ template "galoy.apiKeys.fullname" . }} + spec: + containers: + - name: api-keys + image: "{{ .Values.galoy.images.apiKeys.repository }}@{{ .Values.galoy.images.apiKeys.digest }}" + resources: + {{ toYaml .Values.galoy.apiKeys.resources | nindent 10 }} + ports: + - name: api + containerPort: {{ .Values.galoy.apiKeys.port }} + protocol: TCP + env: + - name: PG_CON + valueFrom: + secretKeyRef: + name: {{ template "galoy.apiKeys.fullname" . }} + key: pg-con + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .Values.tracing.otelExporterGrpcEndpoint | quote }} + - name: API_KEYS_CONFIG + value: "/api-keys.yml" + volumeMounts: + - name: config + mountPath: "/api-keys.yml" + subPath: "api-keys.yml" + readOnly: true + volumes: + - name: config + configMap: + name: {{ template "galoy.apiKeys.fullname" . }} +# TODO: add probes diff --git a/charts/galoy/templates/api-keys-service.yaml b/charts/galoy/templates/api-keys-service.yaml new file mode 100644 index 0000000000..30ee116249 --- /dev/null +++ b/charts/galoy/templates/api-keys-service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "galoy.apiKeys.fullname" . }} + labels: + app: {{ template "galoy.apiKeys.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: Helm +spec: + type: {{ .Values.galoy.apiKeys.serviceType }} + ports: + - port: {{ .Values.galoy.apiKeys.port }} + targetPort: {{ .Values.galoy.apiKeys.port }} + protocol: TCP + name: http + selector: + app: {{ template "galoy.apiKeys.fullname" . }} diff --git a/charts/galoy/templates/balance-notification-cronjob.yaml b/charts/galoy/templates/balance-notification-cronjob.yaml index 7501cc1d34..3c41afddee 100644 --- a/charts/galoy/templates/balance-notification-cronjob.yaml +++ b/charts/galoy/templates/balance-notification-cronjob.yaml @@ -62,14 +62,6 @@ spec: {{ include "galoy.lnd1.env" . | indent 12 }} {{ include "galoy.lnd2.env" . | indent 12 }} - {{ if .Values.galoy.trigger.backups.dropbox.enabled }} - - name: DROPBOX_ACCESS_TOKEN - valueFrom: - secretKeyRef: - name: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.name | quote }} - key: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.key | quote }} - {{ end }} - {{ if .Values.galoy.api.firebaseNotifications.enabled }} - name: GOOGLE_APPLICATION_CREDENTIALS value: "/tmp/service-account.json" diff --git a/charts/galoy/templates/consent-deployment.yaml b/charts/galoy/templates/consent-deployment.yaml new file mode 100644 index 0000000000..9ba6997821 --- /dev/null +++ b/charts/galoy/templates/consent-deployment.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "galoy.consent.fullname" . }} + labels: + app: {{ template "galoy.consent.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: Helm + + kube-monkey/enabled: enabled + kube-monkey/identifier: {{ template "galoy.trigger.fullname" . }} + kube-monkey/kill-mode: fixed + kube-monkey/kill-value: "1" + kube-monkey/mtbf: "8" +spec: + selector: + matchLabels: + app: {{ template "galoy.consent.fullname" . }} + release: {{ .Release.Name }} + replicas: {{ .Values.galoy.consent.replicas }} + template: + metadata: + labels: + app: {{ template "galoy.consent.fullname" . }} + release: "{{ .Release.Name }}" + kube-monkey/enabled: enabled + kube-monkey/identifier: {{ template "galoy.trigger.fullname" . }} + spec: + serviceAccountName: {{ template "galoy.name" . }} + containers: + - name: consent + image: "{{ .Values.galoy.images.consent.repository }}@{{ .Values.galoy.images.consent.digest }}" + resources: + {{- toYaml .Values.resources | nindent 10 }} + ports: + - name: http + containerPort: {{ .Values.galoy.consent.port }} + protocol: TCP + env: + - name: PORT + value: "{{ .Values.galoy.consent.containerPort }}" + - name: GRAPHQL_ENDPOINT + value: {{ .Values.galoy.consent.graphqlPublicApi }} + - name: CORE_AUTH_URL + value: {{ .Values.galoy.consent.coreAuthUrl }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .Values.tracing.otelExporterOtlpEndpoint }} + - name: TRACING_SERVICE_NAME + value: "{{ .Values.tracing.prefix }}-{{ template "galoy.consent.fullname" . }}" + - name: HYDRA_ADMIN_URL + value: {{ .Values.galoy.consent.hydraAdminUrl }} diff --git a/charts/galoy/templates/consent-ingress.yaml b/charts/galoy/templates/consent-ingress.yaml new file mode 100644 index 0000000000..7b10601bbd --- /dev/null +++ b/charts/galoy/templates/consent-ingress.yaml @@ -0,0 +1,40 @@ +{{- if .Values.galoy.consent.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ template "galoy.consent.fullname" . }} + labels: + app: {{ template "galoy.consent.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: Helm + annotations: + cert-manager.io/cluster-issuer: {{ .Values.galoy.consent.ingress.clusterIssuer }} + {{- with .Values.galoy.consent.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: nginx + tls: + {{- range .Values.galoy.consent.ingress.hosts }} + - hosts: + - {{ . }} + secretName: {{ printf "%s-tls" . }} + {{- end }} + rules: + {{- range .Values.galoy.consent.ingress.hosts }} + - host: {{ . }} + http: + paths: + {{- if $.Values.galoy.consent.ingress.extraPaths }} + {{- toYaml $.Values.galoy.consent.ingress.extraPaths | nindent 10 }} + {{- end }} + - pathType: ImplementationSpecific + path: / + backend: + service: + name: {{ template "galoy.consent.fullname" $ }} + port: + number: {{ $.Values.galoy.consent.port }} + {{- end -}} +{{- end -}} diff --git a/charts/galoy/templates/consent-service.yaml b/charts/galoy/templates/consent-service.yaml new file mode 100644 index 0000000000..e2bf8b709b --- /dev/null +++ b/charts/galoy/templates/consent-service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "galoy.consent.fullname" . }} + labels: + app: {{ template "galoy.consent.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: Helm +spec: + type: {{ .Values.galoy.consent.serviceType }} + ports: + - port: {{ .Values.galoy.consent.port }} + targetPort: {{ .Values.galoy.consent.containerPort }} + protocol: TCP + name: http + selector: + app: {{ template "galoy.consent.fullname" . }} diff --git a/charts/galoy/templates/exporter-deployment.yaml b/charts/galoy/templates/exporter-deployment.yaml index 5714a23254..64745dc67b 100644 --- a/charts/galoy/templates/exporter-deployment.yaml +++ b/charts/galoy/templates/exporter-deployment.yaml @@ -48,11 +48,7 @@ spec: containers: - name: exporter - image: "{{ .Values.galoy.images.app.repository }}@{{ .Values.galoy.images.app.digest }}" - args: - - "-r" - - "/app/lib/services/tracing.js" - - "lib/servers/exporter.js" + image: "{{ .Values.galoy.images.exporter.repository }}@{{ .Values.galoy.images.exporter.digest }}" resources: {{ toYaml .Values.galoy.exporter.resources | nindent 10 }} ports: diff --git a/charts/galoy/templates/galoy-cronjob.yaml b/charts/galoy/templates/galoy-cronjob.yaml index c5a53836a6..fc99a8e2e8 100644 --- a/charts/galoy/templates/galoy-cronjob.yaml +++ b/charts/galoy/templates/galoy-cronjob.yaml @@ -19,6 +19,7 @@ spec: template: metadata: labels: + app: {{ template "galoy.cron.jobname" . }} spec: serviceAccountName: {{ template "galoy.name" . }} restartPolicy: OnFailure @@ -32,11 +33,7 @@ spec: containers: - name: {{ template "galoy.cron.jobname" . }} - image: "{{ .Values.galoy.images.app.repository }}@{{ .Values.galoy.images.app.digest }}" - args: - - "-r" - - "/app/lib/services/tracing.js" - - "lib/servers/cron.js" + image: "{{ .Values.galoy.images.cron.repository }}@{{ .Values.galoy.images.cron.digest }}" resources: {{ toYaml .Values.galoy.galoyCron.resources | nindent 14 }} env: @@ -96,14 +93,6 @@ spec: name: {{ .Values.galoy.svixExistingSecret.name }} key: {{ .Values.galoy.svixExistingSecret.secret_key }} - {{ if .Values.galoy.trigger.backups.dropbox.enabled }} - - name: DROPBOX_ACCESS_TOKEN - valueFrom: - secretKeyRef: - name: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.name | quote }} - key: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.key | quote }} - {{ end }} - {{ if .Values.galoy.api.firebaseNotifications.enabled }} - name: GOOGLE_APPLICATION_CREDENTIALS value: "/tmp/service-account.json" diff --git a/charts/galoy/templates/galoy-migration-job.yaml b/charts/galoy/templates/galoy-migration-job.yaml index 8ff380b3bb..d660c81dd0 100644 --- a/charts/galoy/templates/galoy-migration-job.yaml +++ b/charts/galoy/templates/galoy-migration-job.yaml @@ -11,7 +11,7 @@ spec: backoffLimit: 1 template: spec: - {{ if or .Values.galoy.trigger.backups.gcs.enabled .Values.galoy.trigger.backups.dropbox.enabled }} + {{ if or .Values.galoy.trigger.backups.gcs.enabled .Values.galoy.trigger.backups.s3.enabled }} serviceAccountName: {{ template "galoy.name" . }} initContainers: - name: trigger-mongodb-backup diff --git a/charts/galoy/templates/galoy-secrets.yaml b/charts/galoy/templates/galoy-secrets.yaml index fd4c57a861..289e219583 100644 --- a/charts/galoy/templates/galoy-secrets.yaml +++ b/charts/galoy/templates/galoy-secrets.yaml @@ -241,4 +241,18 @@ type: Opaque data: {{ .Values.galoy.proxyCheckExistingSecret.key }}: {{ .Values.secrets.proxyCheckApiKey | toString | b64enc }} +--- + +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "galoy.apiKeys.fullname" . }} + labels: + app: {{ template "galoy.name" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" +type: Opaque +data: + pg-con: {{ .Values.secrets.apiKeysPgCon | toString | b64enc }} + {{- end -}} diff --git a/charts/galoy/templates/mongo-backup-configmap.yaml b/charts/galoy/templates/mongo-backup-configmap.yaml index 3d004b405e..3cb85a7670 100644 --- a/charts/galoy/templates/mongo-backup-configmap.yaml +++ b/charts/galoy/templates/mongo-backup-configmap.yaml @@ -11,25 +11,26 @@ metadata: data: backup.sh: | - {{ if or .Values.galoy.trigger.backups.gcs.enabled .Values.galoy.trigger.backups.dropbox.enabled }} + {{ if or .Values.galoy.trigger.backups.gcs.enabled .Values.galoy.trigger.backups.s3.enabled }} echo "Backup script starts" set -e LOG_TIME=$(date +%s) - BACKUP_NAME="$NETWORK-$LOG_TIME.gz" + BACKUP_NAME="$NETWORK-$LOG_TIME.gz" echo "Backing up mongodb" mongodump --host=$MONGODB_ADDRESS --port=$MONGODB_PORT --username=$MONGODB_USER --password=$MONGODB_PASSWORD --gzip --archive=$BACKUP_NAME -d=$MONGODB_DB --readPreference=secondary - {{ if .Values.galoy.trigger.backups.dropbox.enabled }} - echo "Uploading backup $BACKUP_NAME to dropbox" - curl -X POST https://content.dropboxapi.com/2/files/upload --http1.1 --header "Authorization: Bearer $DROPBOX_ACCESS_TOKEN" --header "Dropbox-API-Arg: {\"path\": \"/mongo/$BACKUP_NAME\"}" --header "Content-Type: application/octet-stream" --data-binary $BACKUP_NAME + {{ if .Values.galoy.trigger.backups.s3.enabled }} + export S3_BUCKET="{{ .Values.galoy.trigger.backups.s3.bucketName }}" + echo "Uploading backup $BACKUP_NAME to s3" + aws s3 cp $BACKUP_NAME s3://$S3_BUCKET/mongodb/$BACKUP_NAME {{ end }} {{ if .Values.galoy.trigger.backups.gcs.enabled }} - export BUCKET_NAME="{{ .Values.galoy.trigger.backups.gcs.bucketName }}" + export GCS_BUCKET="{{ .Values.galoy.trigger.backups.gcs.bucketName }}" echo "Activating service account" gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS echo "Uploading backup $BACKUP_NAME to gcs" - gsutil cp $BACKUP_NAME gs://$BUCKET_NAME/mongodb/$BACKUP_NAME 2>&1 + gsutil cp $BACKUP_NAME gs://$GCS_BUCKET/mongodb/$BACKUP_NAME 2>&1 echo "Uploaded backup successfully" {{ end }} diff --git a/charts/galoy/templates/mongo-backup-cronjob.yaml b/charts/galoy/templates/mongo-backup-cronjob.yaml index c4d1ed7503..ac2ed49f5b 100644 --- a/charts/galoy/templates/mongo-backup-cronjob.yaml +++ b/charts/galoy/templates/mongo-backup-cronjob.yaml @@ -17,6 +17,9 @@ spec: activeDeadlineSeconds: 300 template: + metadata: + labels: + app: {{ template "galoy.mongoBackupCron.jobname" . }} spec: restartPolicy: OnFailure @@ -44,12 +47,19 @@ spec: value: "/var/secret/cloud.google.com/gcs-sa-key.json" {{ end }} - {{ if .Values.galoy.trigger.backups.dropbox.enabled }} - - name: DROPBOX_ACCESS_TOKEN + {{ if .Values.galoy.trigger.backups.s3.enabled }} + - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: - name: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.name | quote }} - key: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.key | quote }} + name: {{ .Values.galoy.trigger.backups.s3.accessKeyExistingSecret.name | quote }} + key: {{ .Values.galoy.trigger.backups.s3.accessKeyExistingSecret.key | quote }} + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.galoy.trigger.backups.s3.secretKeyExistingSecret.name | quote }} + key: {{ .Values.galoy.trigger.backups.s3.secretKeyExistingSecret.key | quote }} + - name: AWS_REGION + value: {{ .Values.galoy.trigger.backups.s3.region | quote }} {{ end }} volumeMounts: diff --git a/charts/galoy/templates/trigger-deployment.yaml b/charts/galoy/templates/trigger-deployment.yaml index 353b632ab9..32eb6da48e 100644 --- a/charts/galoy/templates/trigger-deployment.yaml +++ b/charts/galoy/templates/trigger-deployment.yaml @@ -43,11 +43,7 @@ spec: containers: - name: api - image: "{{ .Values.galoy.images.app.repository }}@{{ .Values.galoy.images.app.digest }}" - args: - - "-r" - - "/app/lib/services/tracing.js" - - "lib/servers/trigger.js" + image: "{{ .Values.galoy.images.trigger.repository }}@{{ .Values.galoy.images.trigger.digest }}" resources: {{ toYaml .Values.galoy.trigger.resources | nindent 10 }} ports: @@ -121,12 +117,19 @@ spec: value: "/var/secret/cloud.google.com/gcs-sa-key.json" {{ end }} - {{ if .Values.galoy.trigger.backups.dropbox.enabled }} - - name: DROPBOX_ACCESS_TOKEN + {{ if .Values.galoy.trigger.backups.s3.enabled }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .Values.galoy.trigger.backups.s3.accessKeyExistingSecret.name | quote }} + key: {{ .Values.galoy.trigger.backups.s3.accessKeyExistingSecret.key | quote }} + - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.name | quote }} - key: {{ .Values.galoy.trigger.backups.dropbox.accessTokenExistingSecret.key | quote }} + name: {{ .Values.galoy.trigger.backups.s3.secretKeyExistingSecret.name | quote }} + key: {{ .Values.galoy.trigger.backups.s3.secretKeyExistingSecret.key | quote }} + - name: AWS_REGION + value: {{ .Values.galoy.trigger.backups.s3.region | quote }} {{ end }} {{ if .Values.galoy.api.firebaseNotifications.enabled }} diff --git a/charts/galoy/templates/websocket-deployment.yaml b/charts/galoy/templates/websocket-deployment.yaml index 3df4397066..6edef676a5 100644 --- a/charts/galoy/templates/websocket-deployment.yaml +++ b/charts/galoy/templates/websocket-deployment.yaml @@ -35,10 +35,6 @@ spec: containers: - name: websocket image: "{{ .Values.galoy.images.websocket.repository }}@{{ .Values.galoy.images.websocket.digest }}" - args: - - "-r" - - "/app/lib/services/tracing.js" - - "lib/servers/ws-server.js" resources: {{ toYaml .Values.galoy.websocket.resources | nindent 10 }} ports: diff --git a/charts/galoy/values.yaml b/charts/galoy/values.yaml index 521ca534cc..4a6e7cb2d2 100644 --- a/charts/galoy/values.yaml +++ b/charts/galoy/values.yaml @@ -33,23 +33,44 @@ galoy: ## Galoy Application Image details ## app: - ## Has api, trigger and exporter - ## - repository: us.gcr.io/galoy-org/galoy-app + repository: us.gcr.io/galoy-org/galoy-api ## Digest of the image ## - digest: "sha256:35fb7e3632f455199f8ed65e67dc41fa9dd127500267e03f587a04a87f0a318d" + digest: "sha256:45e707dd07a30dee9dd4144fa33fd52620a7d62e2f02dfa6c1f194a8167c0d28" ## Not used by Helm, just used to ref to the source https://github.com/GaloyMoney/galoy.git ## Reference for timestamping the corresponding docker image and used by internal CI. ## - git_ref: "7496429" + git_ref: "5825080" websocket: - ## Has websocket + repository: us.gcr.io/galoy-org/galoy-api-ws-server + ## Digest of the image + ## + digest: "sha256:1a9d75c765b57a1817bd9d78fff438b38733da85c9f1c8f0874cae9d1806fb65" + trigger: + repository: us.gcr.io/galoy-org/galoy-api-trigger + ## Digest of the image + ## + digest: "sha256:9b8f297628f6af1851b48b857d027c2bbcf9f0933084b6b79b2563b1b9b05a25" + cron: + repository: us.gcr.io/galoy-org/galoy-api-cron + ## Digest of the image + ## + digest: "sha256:e9a057573dc0e7f961ac043334c57747c1e4effa1fa8d541f3253c2ed2668f9e" + exporter: + repository: us.gcr.io/galoy-org/galoy-api-exporter + ## Digest of the image ## - repository: us.gcr.io/galoy-org/galoy-app-websocket + digest: "sha256:60401fc49dfea9f2b8c5eecbee9ce108f05c1e427d856dafad790278783f89a7" + consent: + repository: us.gcr.io/galoy-org/galoy-consent ## Digest of the image ## - digest: "sha256:bf780cb73f5fe68860056da261bea57cd61180ce9846d38a93ffb38ab9664d92" + digest: "sha256:c9d3d8a18fd64475eb6c6baa1c3ccbb1f2215128a53c0d5c4355945cc4db053f" # METADATA:: repository=https://github.com/GaloyMoney/galoy;commit_ref=e446eda;app=consent; + apiKeys: + repository: us.gcr.io/galoy-org/galoy-api-keys + ## Digest of the image + ## + digest: "sha256:5a1b6144829f4c34ba336a019ed924042db736037d6ad1b21696a5148d1ea8dc" # METADATA:: repository=https://github.com/GaloyMoney/galoy;commit_ref=4242d78;app=api-keys; ## Galoy Application MongoDB Migration Image details ## mongodbMigrate: @@ -58,7 +79,7 @@ galoy: repository: us.gcr.io/galoy-org/galoy-app-migrate ## Digest of the image ## - digest: "sha256:e8487e38cb660f565d6a5d07df12392df811dab82c7e367ab429caa0a5ca7823" + digest: "sha256:c37a9f636b3fcc910a80ce1828cfe58b63dbbc091e0377313eed8dabf65e706a" ## Galoy Application MongoDB Backup Image details ## mongoBackup: @@ -66,11 +87,11 @@ galoy: ## repository: us.gcr.io/galoy-org/mongo-backup ## Digest of the image - digest: "sha256:4cfc197ea082ef3dae2d4321a9dfa31ef185f43d578a37a224095b75de656e6a" + digest: "sha256:66d22e50f472f8fb43a93edec095cd724df2393130d6fa3f17e98906eaedb269" ## Not used by Helm, just used to ref to the source https://github.com/GaloyMoney/galoy.git ## Reference for timestamping the corresponding docker image and used by internal CI. ## - git_ref: "872b70e" + git_ref: "ce9792c" ## Configuration values for Galoy API components. ## api: @@ -117,6 +138,13 @@ galoy: name: galoyapp-firebase-serviceaccount # Secret Key key: galoyapp-firebase-serviceaccount.json + ## CAUTION - UNSECURE FLAG! + ## Enable Unsercure default logins to any phone number via the code + unsecureDefaultLoginCode: + enabled: false # Should be disabled in all production systems + existingSecret: + name: galoyapp-unsecure-login-code + key: code ## Liveness/Readiness Probes Configuration ## Determines if pod is healthy or if it should be killed. ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ @@ -197,19 +225,29 @@ galoy: name: gcs-sa-key # Secret Key key: gcs-sa-key.json - ## Backup data to Dropbox - ## To backup to dropbox, you would need an access token to upload - ## data to your dropbox account + ## Backup data to S3 bucket + ## To backup to S3 bucket, you would need an access key and secret key + ## to upload data to your S3 bucket ## - dropbox: - # Enable/disable uploading backup to dropbox + s3: + # Enable/disable uploading backup to S3 bucket enabled: false - # Dropbox Access Token must be injected via a secret - accessTokenExistingSecret: - # Secret Name - name: dropbox-access-token + # S3 bucket name to upload to (it should already be created) + bucketName: s3-bucket-name + # Aws region + region: us-east-1 + # S3 access key to use to upload backup to above-mentioned bucket + accessKeyExistingSecret: + # Secret name + name: s3-creds # Secret Key - key: token + key: access-key + # S3 secret key to use to upload backup to above-mentioned bucket + secretKeyExistingSecret: + # Secret name + name: s3-creds + # Secret Key + key: secret-key ## Configuration values for Galoy Admin components. ## admin: @@ -363,6 +401,26 @@ galoy: failureThreshold: 5 successThreshold: 2 timeoutSeconds: 1 + apiKeys: + nameOverride: + replicas: 2 + port: 5397 + serviceType: ClusterIP + resources: {} + config: + keyPrefix: galoy + consent: + resources: {} + port: 80 + containerPort: 3000 + graphqlPublicApi: http://galoy-oathkeeper-proxy:4455/graphql + coreAuthUrl: http://galoy-oathkeeper-proxy:4455/auth + hydraAdminUrl: http://galoy-hydra-admin:4445 + ingress: + enabled: false + hosts: [consent.staging.galoy.io] + clusterIssuer: letsencrypt-issuer + tlsSecretName: consent-tls mongoBackupCron: resources: {} galoyCron: @@ -623,12 +681,15 @@ secrets: svixSecretKey: ## Api key for proxy check proxyCheckApiKey: + ## postgres secret for api-keys + apiKeysPgCon: ## Tracing details ## tracing: ## OTEL Exporter OTLP Endpoint ## otelExporterOtlpEndpoint: http://localhost:4318 + otelExporterGrpcEndpoint: http://localhost:4317 ## Prefix for tracing ## prefix: galoy-dev @@ -673,6 +734,12 @@ oathkeeper: preserve_path: true subject_from: identity.id extra_from: identity.traits + oauth2_introspection: + enabled: true + config: + introspection_url: http://galoy-hydra-admin:4445/admin/oauth2/introspect + token_from: + header: Oauth2-Token anonymous: enabled: true config: @@ -697,6 +764,12 @@ oathkeeper: config: jwks_url: "http://galoy-oathkeeper-api:4456/.well-known/jwks.json" issuer_url: "galoy.io" + header: + enabled: true + config: + headers: + X-Appcheck-Jti: "{{ print .Extra.jti }}" + Authorization: '{{ .MatchContext.Header.Get "Authorization" }}' errors: fallback: - json @@ -709,131 +782,103 @@ oathkeeper: matching_strategy: regexp mutatorIdTokenJWKs: "http://galoy-oathkeeper-api:4456/.well-known/jwks.json" accessRules: | - [ - { - "id": "anonymous-rest-auth", - "upstream": { "url": "http://api:4002" }, - "match": { - "url": "<(http|https)>://<[a-zA-Z0-9-.:]+>/auth/<(clearCookies|login|logout|email/code|email/login|email/login/cookie)>", - "methods": ["GET", "POST", "OPTIONS"] - }, - "authenticators": [{ "handler": "anonymous" }], - "authorizer": { "handler": "allow" }, - "mutators": [{ "handler": "noop" }] - }, - { - "id": "device-login", - "upstream": { - "url": "http://api:4002" - }, - "match": { - "url": "<(http|https)>://<[a-zA-Z0-9-.:]+>/auth/create/device-account", - "methods": ["POST"] - }, - "authenticators": [ - { - "handler": "jwt", - "config": { - "trusted_issuers": [ "https://firebaseappcheck.googleapis.com/72279297366" ], - "target_audience": [ "projects/72279297366" ], - "jwks_urls": [ "https://firebaseappcheck.googleapis.com/v1beta/jwks" ], - "token_from": { - "header": "Appcheck" - } - } - }, - ], - "authorizer": { "handler": "allow" }, - "mutators": [{ "handler": "noop" }] - }, - { - "id": "galoy-router", - "upstream": { - "url": "http://galoy-router:80" - }, - "match": { - "url": "<(http|https)>://<[a-zA-Z0-9-.:]+>/graphql", - "methods": [ "POST", "GET", "OPTIONS" ] - }, - "authenticators": [ - { - "handler": "cookie_session", - "config": { - "check_session_url": "http://galoy-kratos-public:80/sessions/whoami", - "preserve_path": true, - "preserve_query": true, - "subject_from": "identity.id", - "extra_from": "@this" - } - }, - { - "handler": "bearer_token", - "config": { - "check_session_url": "http://galoy-kratos-public:80/sessions/whoami", - "preserve_path": true, - "preserve_query": true, - "subject_from": "identity.id", - "extra_from": "@this" - } - }, - { "handler": "anonymous" } - ], - "authorizer": { "handler": "allow" }, - "mutators": [ - { - "handler": "id_token", - "config": { - "claims": '{"sub": "{{ print .Subject }}", "session_id": "{{ print .Extra.id }}", "expires_at": "{{ print .Extra.expires_at }}" }' - } - } - ] - }, - { - "id": "admin-backend", - "upstream": { - "url": "http://graphql-admin:4001", - "strip_path": "/admin" - }, - "match": { - "url": "<(http|https)>://<.*><[0-9]*>/admin/<.*>", - "methods": ["GET", "POST", "OPTIONS"] - }, - "authenticators": [ - { - "handler": "cookie_session", - "config": { - "check_session_url": "http://galoy-kratos-public:80/sessions/whoami", - "preserve_path": true, - "preserve_query": true, - "subject_from": "identity.id", - "extra_from": "@this" - } - }, - { - "handler": "bearer_token", - "config": { - "check_session_url": "http://galoy-kratos-public:80/sessions/whoami", - "preserve_path": true, - "preserve_query": true, - "subject_from": "identity.id", - "extra_from": "@this" - } - }, - { "handler": "anonymous" } - ], - "authorizer": { - "handler": "allow" - }, - "mutators": [ - { - "handler": "id_token", - "config": { - "claims": '{"sub": "{{ print .Subject }}"}' - } - } - ] - } - ] + - id: anonymous-rest-auth + upstream: + url: http://api:4002 + match: + url: "<(http|https)>://<[a-zA-Z0-9-.:]+>/auth/<.*>" + methods: + - GET + - POST + - OPTIONS + authenticators: + - handler: jwt + config: + trusted_issuers: + - https://firebaseappcheck.googleapis.com/72279297366 + target_audience: + - projects/72279297366 + jwks_urls: + - https://firebaseappcheck.googleapis.com/v1beta/jwks + token_from: + header: Appcheck + - handler: anonymous + authorizer: + handler: allow + mutators: + - handler: header + - id: galoy-router + upstream: + url: http://galoy-router:80 + match: + url: "<(http|https)>://<[a-zA-Z0-9-.:]+>/graphql" + methods: + - POST + - GET + - OPTIONS + authenticators: + - handler: cookie_session + config: + check_session_url: http://galoy-kratos-public:80/sessions/whoami + preserve_path: true + preserve_query: true + subject_from: identity.id + extra_from: "@this" + - handler: bearer_token + config: + check_session_url: http://galoy-kratos-public:80/sessions/whoami + preserve_path: true + preserve_query: true + subject_from: identity.id + extra_from: "@this" + - handler: bearer_token + config: + token_from: + header: X-API-KEY + forward_http_headers: + - "X-API-KEY" + check_session_url: "http://api-keys:5397/auth/check" + force_method: GET + preserve_path: true + preserve_query: true + subject_from: sub + extra_from: "@this" + - handler: anonymous + authorizer: + handler: allow + mutators: + - handler: id_token + config: + claims: '{"sub": "{{ print .Subject }}", "session_id": "{{ print .Extra.id }}", "expires_at": "{{ print .Extra.expires_at }}" }' + - id: admin-backend + upstream: + url: http://graphql-admin:4001 + strip_path: /admin + match: + url: "<(http|https)>://<.*><[0-9]*>/admin/<.*>" + methods: + - GET + - POST + - OPTIONS + authenticators: + - handler: cookie_session + config: + check_session_url: http://galoy-kratos-public:80/sessions/whoami + preserve_path: true + preserve_query: true + subject_from: identity.id + extra_from: "@this" + - handler: oauth2_introspection + config: + introspection_url: http://galoy-hydra-admin:4445/admin/oauth2/introspect + token_from: + header: Oauth2-Token + authorizer: + handler: allow + mutators: + - handler: id_token + config: + claims: '{"sub": "{{ print .Subject }}", "scope": "{{ print .Extra.scope }}" }' maester: enabled: false kratos: @@ -858,6 +903,8 @@ kratos: domain: localhost # var.root_domain serve: public: + request_log: + disable_for_health: true base_url: http://galoy-kratos-public:80/ cors: enabled: true @@ -878,6 +925,8 @@ kratos: - Set-Cookie debug: true admin: + request_log: + disable_for_health: true base_url: http://galoy-kratos-admin:80/ selfservice: default_browser_return_url: http://localhost:3000/ @@ -1151,6 +1200,24 @@ kratos: } } emailTemplates: {} +hydra: + enabled: true + replicaCount: 2 + maester: + enabled: false + hydra: + config: + dsn: memory + dev: true + serve: + cookies: + same_site_mode: Lax + urls: + self: + issuer: http://127.0.0.1:4444 + consent: http://127.0.0.1:3000/consent + login: http://127.0.0.1:3000/login + logout: http://127.0.0.1:3000/logout router: supergraphFilePath: apollo-router/supergraph.graphql extraEnvVars: diff --git a/charts/lnd/Chart.yaml b/charts/lnd/Chart.yaml index 0816334bd5..32910e312a 100644 --- a/charts/lnd/Chart.yaml +++ b/charts/lnd/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: lnd -version: 0.7.3-dev +version: 0.9.1-dev appVersion: 0.16.1 description: LND helm chart keywords: diff --git a/charts/lnd/values.yaml b/charts/lnd/values.yaml index 9d56aa1c76..eb857496aa 100644 --- a/charts/lnd/values.yaml +++ b/charts/lnd/values.yaml @@ -2,12 +2,12 @@ global: network: mainnet image: repository: lightninglabs/lnd - tag: v0.16.2-beta + tag: v0.17.3-beta pullPolicy: IfNotPresent sidecarImage: repository: us.gcr.io/galoy-org/lnd-sidecar - digest: "sha256:e3ad153f0fe8dc8418c0e0c3cc6baf74ecc2a6b7c1436a6154e52330eb02167f" - git_ref: 2614f2e + digest: "sha256:f748f0728d4db112e2961beb58d7b4e4e6f25e36441454ec777dc02603501b4f" + git_ref: 083c7f7 kubemonkey: enabled: false configmap: diff --git a/charts/loop/charts/loopserver/templates/pvc.yml b/charts/loop/charts/loopserver/templates/pvc.yml index a2cb055c3f..0a0c8b8fbd 100644 --- a/charts/loop/charts/loopserver/templates/pvc.yml +++ b/charts/loop/charts/loopserver/templates/pvc.yml @@ -3,8 +3,6 @@ kind: PersistentVolumeClaim apiVersion: v1 metadata: name: {{ template "loopserver.fullname" $ }} - annotations: - "helm.sh/resource-policy": keep labels: {{- include "loopserver.labels" . | nindent 4 }} spec: diff --git a/charts/mempool/values.yaml b/charts/mempool/values.yaml index 123ee95b92..2227c30d04 100644 --- a/charts/mempool/values.yaml +++ b/charts/mempool/values.yaml @@ -1,7 +1,7 @@ image: repository: mempool/backend pullPolicy: IfNotPresent - tag: v2.5.0 + tag: v3.0.0-dev1 service: type: ClusterIP diff --git a/charts/monitoring/Chart.lock b/charts/monitoring/Chart.lock index 415c6919bb..88ee5eb070 100644 --- a/charts/monitoring/Chart.lock +++ b/charts/monitoring/Chart.lock @@ -1,9 +1,9 @@ dependencies: - name: grafana repository: https://grafana.github.io/helm-charts - version: 6.59.4 + version: 7.0.19 - name: prometheus repository: https://prometheus-community.github.io/helm-charts - version: 25.0.0 -digest: sha256:3710d3e4f501e6f8f7d2055226fa86c0fd6ab859df3b3de7ac2f5577623fa912 -generated: "2023-09-19T03:05:31.533173448Z" + version: 25.8.2 +digest: sha256:04812f45e5d42640de6aab913f02658793ea08cee35de2a03c852d47d0acb0cd +generated: "2023-12-19T01:43:02.994830054Z" diff --git a/charts/monitoring/Chart.yaml b/charts/monitoring/Chart.yaml index 9eca16dc83..4a66c49c34 100644 --- a/charts/monitoring/Chart.yaml +++ b/charts/monitoring/Chart.yaml @@ -13,7 +13,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.7.6-dev +version: 0.11.2-dev # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. @@ -21,7 +21,7 @@ appVersion: 0.1.0 dependencies: - name: grafana repository: https://grafana.github.io/helm-charts - version: 6.59.4 + version: 7.0.19 - name: prometheus repository: https://prometheus-community.github.io/helm-charts - version: 25.0.0 + version: 25.8.2 diff --git a/charts/stablesats/Chart.lock b/charts/stablesats/Chart.lock index 878c1f553e..be3d39a0a5 100644 --- a/charts/stablesats/Chart.lock +++ b/charts/stablesats/Chart.lock @@ -2,5 +2,5 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami version: 11.9.6 -digest: sha256:9dd24083749c3f2a0eb927738ab689d3e95a018f6b38874ba2c13569aeee2f08 -generated: "2023-08-02T09:47:09.978376512Z" +digest: sha256:e9f252a13edc2a9ecde83ea222591e1767aa08f97fb7c9071d69c49bff78a481 +generated: "2023-11-08T13:12:10.384230687+05:30" diff --git a/charts/stablesats/Chart.yaml b/charts/stablesats/Chart.yaml index 5dc5b14cc0..0c7bfa453e 100644 --- a/charts/stablesats/Chart.yaml +++ b/charts/stablesats/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: stablesats description: A Helm chart for Kubernetes type: application -version: 0.12.1-dev -appVersion: 0.9.23 +version: 0.17.0-dev +appVersion: 0.12.0 dependencies: - name: postgresql version: 11.9.6 diff --git a/charts/stablesats/values.yaml b/charts/stablesats/values.yaml index bd768f9560..ce914e8934 100644 --- a/charts/stablesats/values.yaml +++ b/charts/stablesats/values.yaml @@ -14,8 +14,7 @@ stablesats: resources: {} image: repository: us.gcr.io/galoy-org/stablesats-rs - digest: "sha256:9b9c64ac757423fb048ade6e75683a22326b93b55b623153fb31d51053495b49" - git_ref: "cbc7756" + digest: "sha256:a63c22f2d7586a55a0c31049550f2120441448c6d54a79bec64ce7167c599a23" # METADATA:: repository=https://github.com/GaloyMoney/stablesats-rs;commit_ref=815fae1;app=stablesats; crash_report_config_danger: false db: poolSize: 20 diff --git a/charts/web-wallet/templates/deployment.yaml b/charts/web-wallet/templates/deployment.yaml deleted file mode 100644 index c7e52554c6..0000000000 --- a/charts/web-wallet/templates/deployment.yaml +++ /dev/null @@ -1,77 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "webWallet.fullname" . }} - labels: - app: {{ template "webWallet.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - release: "{{ .Release.Name }}" -spec: - selector: - matchLabels: - app: {{ template "webWallet.fullname" . }} - release: {{ .Release.Name }} - replicas: 1 - template: - metadata: - labels: - app: {{ template "webWallet.fullname" . }} - release: "{{ .Release.Name }}" -{{- with .Values.labels }} -{{ toYaml . | trim | indent 8 }} -{{- end }} - spec: - containers: - - name: web-wallet - {{- if eq .Values.mobileLayout.enabled true }} - image: "{{ .Values.mobileLayout.image.repository }}@{{ .Values.mobileLayout.image.digest }}" - {{- else }} - image: "{{ .Values.image.repository }}@{{ .Values.image.digest }}" - {{- end }} - ports: - - containerPort: 3000 - env: - - name: NODE_ENV - value: production - - name: JAEGER_HOST - value: {{ $.Values.webWallet.jaegerHost }} - - name: TRACING_SERVICE_NAME - value: {{ $.Values.webWallet.tracingPrefix }}-web-wallet - - name: SESSION_KEYS - valueFrom: - secretKeyRef: - name: {{ template "webWallet.fullname" . }} - key: session-keys - - name: HOST - value: 0.0.0.0 - - name: PORT - value: "3000" - - name: NETWORK - value: {{ .Values.webWallet.bitcoinNetwork }} - - name: SUPPORT_EMAIL - value: {{ .Values.webWallet.supportEmail }} - - name: GRAPHQL_URL - value: {{ .Values.webWallet.graphqlUrl }} - - name: GRAPHQL_SUBSCRIPTION_URL - value: {{ .Values.webWallet.graphqlSubscriptionUrl }} - - name: AUTH_ENDPOINT - value: {{ .Values.webWallet.authEndpoint }} - - name: WALLET_NAME - value: {{ .Values.webWallet.walletName }} - - name: SHARE_URL - value: {{ .Values.webWallet.galoyPayEndpoint }} - - name: GALOY_AUTH_ENDPOINT - value: {{ .Values.webWallet.galoyAuthEndpoint }} - {{- if eq .Values.webWallet.kratos.enabled true }} - - name: KRATOS_API_URL - value: {{ .Values.webWallet.kratos.apiUrl }} - - name: KRATOS_BROWSER_URL - value: {{ .Values.webWallet.kratos.browserUrl }} - - name: KRATOS_FEATURE_FLAG - value: "true" - {{- end }} - resources: - {{ toYaml .Values.resources | nindent 10 }} -{{- if .Values.webWallet.additionalEnvVars }} -{{ toYaml .Values.webWallet.additionalEnvVars | indent 8 }} -{{- end }} diff --git a/charts/web-wallet/templates/secrets.yaml b/charts/web-wallet/templates/secrets.yaml deleted file mode 100644 index e12a74ce32..0000000000 --- a/charts/web-wallet/templates/secrets.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.secrets.create }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "webWallet.fullname" . }} - labels: - app: {{ template "webWallet.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - release: "{{ .Release.Name }}" - {{- if .Values.secrets.annotations }} - annotations: -{{ toYaml .Values.secrets.annotations | indent 4 }} - {{- end }} -type: Opaque -data: - session-keys: {{ required "secrets.sessionKeys needs to be set when secrets.create=true" .Values.secrets.sessionKeys | b64enc | quote }} -{{- end }} diff --git a/charts/web-wallet/values.yaml b/charts/web-wallet/values.yaml deleted file mode 100644 index 495507c70c..0000000000 --- a/charts/web-wallet/values.yaml +++ /dev/null @@ -1,39 +0,0 @@ -image: - repository: us.gcr.io/galoy-org/web-wallet - digest: "sha256:53a370c83f0f16868e41a3029be222f8c8624b5e6482182bd4b097cf25ef9674" - git_ref: "2b7d532" # Not used by helm -mobileLayout: - enabled: false - image: - repository: us.gcr.io/galoy-org/web-wallet-mobile-layout - digest: "sha256:53a370c83f0f16868e41a3029be222f8c8624b5e6482182bd4b097cf25ef9674" -ingress: - enabled: false -service: - port: 80 - type: ClusterIP -webWallet: - jaegerHost: localhost - tracingPrefix: "galoy" - bitcoinNetwork: regtest - authEndpoint: api/login - graphqlUrl: http://localhost:4002/graphql - graphqlSubscriptionUrl: ws://localhost:4002/graphql - supportEmail: support@galoy.io - walletName: galoy - galoyPayEndpoint: http://localhost:4000 - galoyAuthEndpoint: http://localhost:4002/auth - kratos: - enabled: false - browserUrl: http://localhost:4433 - apiUrl: http://localhost:4433 -secrets: - ## Create the secret resource from the following values. Set this to - ## false to manage these secrets outside Helm. - ## Checkout templates/secrets.yaml to get the appropriate template - ## Set this to true and set secrets.sessionKeys to the - ## value of the session key to have a secret be created - create: false - ## cookieSession keys - sessionKeys: "session-keys" -resources: {} diff --git a/ci/pipeline-fragments.lib.yml b/ci/pipeline-fragments.lib.yml index ab73ee1178..bae50178fd 100644 --- a/ci/pipeline-fragments.lib.yml +++ b/ci/pipeline-fragments.lib.yml @@ -44,7 +44,7 @@ source: #@ bitcoin_charts = ["bitcoind", "lnd", "rtl", "specter", "bria", "fulcrum", "mempool"] -#@ addons_charts = ["admin-panel", "galoy-pay", "web-wallet"] +#@ addons_charts = ["admin-panel", "galoy-pay", "api-dashboard"] #@ def testflight_job(chart, deployment, vars = {}): name: #@ testflight_job_name(chart) diff --git a/ci/pipeline.yml b/ci/pipeline.yml index 4b2cc7876c..fce731d90c 100644 --- a/ci/pipeline.yml +++ b/ci/pipeline.yml @@ -267,7 +267,7 @@ jobs: - name: charts-repo params: BRANCH: #@ data.values.git_branch - IMAGE_KEY_PATH: mongobackup.image + IMAGE_KEY_PATH: galoy.images.mongoBackup IMAGE: mongo-backup CHART: galoy run: @@ -289,7 +289,7 @@ jobs: GH_TOKEN: #@ data.values.github_token BRANCH: #@ data.values.git_branch BOT_BRANCH: #@ data.values.git_mongo_backup_bot_branch - IMAGE_KEY_PATH: mongobackup.image + IMAGE_KEY_PATH: galoy.images.mongoBackup IMAGE: mongo-backup CHART: galoy run: diff --git a/ci/tasks/api-dashboard-smoketest.sh b/ci/tasks/api-dashboard-smoketest.sh new file mode 100755 index 0000000000..1e22cf83ca --- /dev/null +++ b/ci/tasks/api-dashboard-smoketest.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -eu + +source smoketest-settings/helpers.sh + +host=`setting "api_dashboard_endpoint"` +port=`setting "api_dashboard_port"` + +set +e +for i in {1..15}; do + echo "Attempt ${i} to curl admin panel" + curl --location -f ${host}:${port} + if [[ $? == 0 ]]; then success="true"; break; fi; + sleep 1 +done +set -e + +if [[ "$success" != "true" ]]; then echo "Smoke test failed" && exit 1; fi; diff --git a/ci/tasks/galoy-smoketest.sh b/ci/tasks/galoy-smoketest.sh index 0d1350d80b..428d116be3 100755 --- a/ci/tasks/galoy-smoketest.sh +++ b/ci/tasks/galoy-smoketest.sh @@ -22,7 +22,7 @@ for i in {1..15}; do echo "Attempt ${i} to curl the public galoy API" curl --location -sSf --request POST "${host}:${port}/graphql"\ --header 'Content-Type: application/json' \ - --data-raw '{"query":"query btcPrice { btcPrice { base currencyUnit formattedAmount offset } }","variables":{}}' > response.json + --data-raw '{"query":"query realtimePrice { realtimePrice { id timestamp btcSatPrice { base offset } } }","variables":{}}' > response.json if [[ $? == 0 ]]; then success="true"; break; fi; sleep 1 done diff --git a/ci/tasks/web-wallet-smoketest.sh b/ci/tasks/web-wallet-smoketest.sh deleted file mode 100755 index 268f12a7dd..0000000000 --- a/ci/tasks/web-wallet-smoketest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -set -eu - -source smoketest-settings/helpers.sh - -host=`setting "web_wallet_endpoint"` -web_wallet_mobile_host=`setting "web_wallet_mobile_endpoint"` -port=`setting "web_wallet_port"` - -set +e -for i in {1..15}; do - echo "Attempt ${i} to curl web wallet" - curl --location -f ${host}:${port} - status=$? - if [[ web_wallet_mobile_host != "" ]]; then curl --location -f ${web_wallet_mobile_host}:${port} - else echo "Skipping secondary host - not configured." - fi - if [[ $status == 0 ]] && [[ $? == 0 ]]; then success="true"; break; fi; - sleep 1 -done -set -e - -if [[ "$success" != "true" ]]; then echo "Smoke test failed" && exit 1; fi; diff --git a/ci/testflight/admin-panel/main.tf b/ci/testflight/admin-panel/main.tf index 80ff7857e5..626adbf1a9 100644 --- a/ci/testflight/admin-panel/main.tf +++ b/ci/testflight/admin-panel/main.tf @@ -26,11 +26,30 @@ resource "kubernetes_secret" "smoketest" { } } +resource "kubernetes_secret" "admin_panel" { + metadata { + name = "admin-panel" + namespace = local.testflight_namespace + } + + data = { + "next-auth-secret" : "dummy123" + "google-oauth-client-id" : "dummy" + "google-oauth-client-secret" : "dummy" + "github-oauth-client-id" : "dummy" + "github-oauth-client-secret" : "dummy" + } +} + resource "helm_release" "admin_panel" { name = "admin-panel" chart = "${path.module}/chart" repository = "https://galoymoney.github.io/charts/" namespace = kubernetes_namespace.testflight.metadata[0].name + + values = [ + file("${path.module}/testflight-values.yml") + ] } data "google_container_cluster" "primary" { diff --git a/ci/testflight/admin-panel/testflight-values.yml b/ci/testflight/admin-panel/testflight-values.yml new file mode 100644 index 0000000000..b42ed43549 --- /dev/null +++ b/ci/testflight/admin-panel/testflight-values.yml @@ -0,0 +1,2 @@ +secrets: + create: false diff --git a/ci/testflight/web-wallet/main.tf b/ci/testflight/api-dashboard/main.tf similarity index 68% rename from ci/testflight/web-wallet/main.tf rename to ci/testflight/api-dashboard/main.tf index 09daa274c2..d3c9615141 100644 --- a/ci/testflight/web-wallet/main.tf +++ b/ci/testflight/api-dashboard/main.tf @@ -7,8 +7,6 @@ locals { smoketest_namespace = "galoy-staging-smoketest" testflight_namespace = var.testflight_namespace - - session_keys = "session-keys" } resource "kubernetes_namespace" "testflight" { @@ -23,47 +21,31 @@ resource "kubernetes_secret" "smoketest" { namespace = local.smoketest_namespace } data = { - web_wallet_endpoint = "web-wallet.${local.testflight_namespace}.svc.cluster.local" - web_wallet_mobile_endpoint = "web-wallet-mobile.${local.testflight_namespace}.svc.cluster.local" - web_wallet_port = 80 + api_dashboard_endpoint = "api-dashboard.${local.testflight_namespace}.svc.cluster.local" + api_dashboard_port = 3000 } } -resource "kubernetes_secret" "web_wallet" { +resource "kubernetes_secret" "api_dashboard" { metadata { - name = "web-wallet" + name = "api-dashboard" namespace = local.testflight_namespace } - data = { - "session-keys" : local.session_keys - } -} - -resource "helm_release" "web_wallet" { - name = "web-wallet" - chart = "${path.module}/chart" - repository = "https://galoymoney.github.io/charts/" - namespace = kubernetes_namespace.testflight.metadata[0].name -} -resource "kubernetes_secret" "web_wallet_mobile" { - metadata { - name = "web-wallet-mobile" - namespace = local.testflight_namespace - } data = { - "session-keys" : local.session_keys + "next-auth-secret" : "dummy123" + "client-secret" : "dummy" } } -resource "helm_release" "web_wallet_mobile" { - name = "web-wallet-mobile" +resource "helm_release" "api_dashboard" { + name = "api-dashboard" chart = "${path.module}/chart" repository = "https://galoymoney.github.io/charts/" namespace = kubernetes_namespace.testflight.metadata[0].name values = [ - file("${path.module}/web-wallet-mobile-testflight-values.yml") + file("${path.module}/testflight-values.yml") ] } diff --git a/ci/testflight/api-dashboard/testflight-values.yml b/ci/testflight/api-dashboard/testflight-values.yml new file mode 100644 index 0000000000..fef2266f0f --- /dev/null +++ b/ci/testflight/api-dashboard/testflight-values.yml @@ -0,0 +1,7 @@ +secrets: + create: false + +apiDashboard: + hydraPublic: "http://galoy-hydra-public.galoy-staging-galoy.svc.cluster.local:4444" + coreUrl: "http://galoy-oathkeeper-proxy.galoy-staging-galoy.svc.cluster.local:4455/graphql" + nextAuthUrl: "http://api-dashboard:3000" diff --git a/ci/testflight/galoy-pay/testflight-values.yml b/ci/testflight/galoy-pay/testflight-values.yml index 3ff18bf17e..ce1ff6d941 100644 --- a/ci/testflight/galoy-pay/testflight-values.yml +++ b/ci/testflight/galoy-pay/testflight-values.yml @@ -9,6 +9,6 @@ redis: redis0Dns: galoy-redis-node-0.galoy-redis-headless.galoy-staging-galoy.svc.cluster.local redis1Dns: galoy-redis-node-1.galoy-redis-headless.galoy-staging-galoy.svc.cluster.local redis2Dns: galoy-redis-node-2.galoy-redis-headless.galoy-staging-galoy.svc.cluster.local -graphqlUrl: http://api.galoy-staging-galoy.svc.cluster.local/graphql -graphqlUrlInternal: http://api.galoy-staging-galoy.svc.cluster.local/graphql -graphqlWebsocketUrl: wss://ws.galoy-staging-galoy.svc.cluster.local/graphql +coreGqlUrlIntranet: http://api.galoy-staging-galoy.svc.cluster.local/graphql +payUrl: http://pay.galoy-staging-galoy.svc.cluster.local/graphql +payDomain: galoy-staging-galoy.svc.cluster.local diff --git a/ci/testflight/galoy/api-keys-postgresql-values.yml b/ci/testflight/galoy/api-keys-postgresql-values.yml new file mode 100644 index 0000000000..df86c7a81f --- /dev/null +++ b/ci/testflight/galoy/api-keys-postgresql-values.yml @@ -0,0 +1,11 @@ +# Settings from: +# https://github.com/bitnami/charts/blob/main/bitnami/postgresql/values.yaml + +auth: + username: api-keys + password: api-keys + database: api-keys + +primary: + persistence: + enabled: false diff --git a/ci/testflight/galoy/main.tf b/ci/testflight/galoy/main.tf index 11484110af..0984ca7832 100644 --- a/ci/testflight/galoy/main.tf +++ b/ci/testflight/galoy/main.tf @@ -61,17 +61,6 @@ resource "kubernetes_secret" "geetest_key" { } } -resource "kubernetes_secret" "dropbox_access_token" { - metadata { - name = "dropbox-access-token" - namespace = kubernetes_namespace.testflight.metadata[0].name - } - - data = { - token = "dummy" - } -} - resource "kubernetes_secret" "mongodb_creds" { metadata { name = "galoy-mongodb" @@ -192,7 +181,7 @@ resource "kubernetes_secret" "lnd1_credentials" { data "kubernetes_secret" "loop1_credentials" { metadata { - name = "loop1-credentials" + name = "lnd1-loop-credentials" namespace = local.bitcoin_namespace } } @@ -208,7 +197,7 @@ resource "kubernetes_secret" "loop1_credentials" { data "kubernetes_secret" "loop2_credentials" { metadata { - name = "loop2-credentials" + name = "lnd2-loop-credentials" namespace = local.bitcoin_namespace } } @@ -343,6 +332,16 @@ resource "kubernetes_secret" "proxy_check_api_key" { } } +resource "kubernetes_secret" "api_keys" { + metadata { + name = "api-keys" + namespace = kubernetes_namespace.testflight.metadata[0].name + } + data = { + pg-con : "postgres://api-keys:api-keys@api-keys-postgresql:5432/api-keys" + } +} + resource "helm_release" "postgresql" { name = "postgresql" repository = "https://charts.bitnami.com/bitnami" @@ -355,6 +354,18 @@ resource "helm_release" "postgresql" { ] } +resource "helm_release" "api_keys_postgresql" { + name = "api-keys-postgresql" + repository = "https://charts.bitnami.com/bitnami" + chart = "postgresql" + version = "11.9.13" + namespace = kubernetes_namespace.testflight.metadata[0].name + + values = [ + file("${path.module}/api-keys-postgresql-values.yml") + ] +} + resource "helm_release" "galoy" { name = "galoy" chart = "${path.module}/chart" diff --git a/ci/testflight/galoy/testflight-values.yml b/ci/testflight/galoy/testflight-values.yml index 5551a4f563..1eee3a3187 100644 --- a/ci/testflight/galoy/testflight-values.yml +++ b/ci/testflight/galoy/testflight-values.yml @@ -6,8 +6,6 @@ galoy: gcs: enabled: true bucketName: galoy-staging-backups - dropbox: - enabled: true api: replicas: 1 diff --git a/ci/testflight/web-wallet/web-wallet-mobile-testflight-values.yml b/ci/testflight/web-wallet/web-wallet-mobile-testflight-values.yml deleted file mode 100644 index 9371a1598a..0000000000 --- a/ci/testflight/web-wallet/web-wallet-mobile-testflight-values.yml +++ /dev/null @@ -1,2 +0,0 @@ -mobileLayout: - enabled: true diff --git a/dev/.envrc b/dev/.envrc deleted file mode 100644 index 35abc1222f..0000000000 --- a/dev/.envrc +++ /dev/null @@ -1,4 +0,0 @@ -use flake . - -export KUBE_CONFIG_PATH=~/.kube/config -export KUBE_CTX=k3d-k3s-default diff --git a/dev/Makefile b/dev/Makefile index d07e7b740e..3b6db738f1 100644 --- a/dev/Makefile +++ b/dev/Makefile @@ -9,132 +9,26 @@ create-cluster: delete-cluster: k3d cluster delete && rm terraform.tfstate -init: - terraform init - -deploy-services: - $(TF) apply -target module.galoy_deps.helm_release.cert_manager \ - -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - $(TF) apply -target module.galoy_deps \ - -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - -destroy-services: - $(TF) destroy -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - - -redeploy-kafka: - -kubectl delete namespace galoy-dev-kafka --force - $(TF) apply -target=module.galoy_deps.helm_release.kafka \ - -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - cd kafka-connect - $(TF) apply -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - -deploy: - $(TF) apply -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - all: create-cluster init deploy-services deploy -refresh: - $(TF) refresh -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" - $(TF) apply -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - -redeploy-bitcoin: - -kubectl delete namespace galoy-dev-bitcoin --force - cd bitcoin - $(TF) apply -target module.bitcoin -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - -redeploy-galoy: - -kubectl delete namespace galoy-dev-galoy --force - cd galoy - $(TF) apply -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - -redeploy-monitoring: - -kubectl delete namespace galoy-dev-monitoring --force - cd monitoring - $(TF) apply -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - -redeploy-smoketest: - -kubectl delete namespace galoy-dev-smoketest --force - cd smoketest - $(TF) apply -var="bitcoin_network=regtest" \ - -var="name_prefix=galoy-dev" -auto-approve - - -deploy-signet-services: - $(TF) apply -target module.galoy_deps.helm_release.cert_manager \ - -var="bitcoin_network=signet" \ - -var="name_prefix=galoy-sig" -auto-approve - $(TF) apply -target module.galoy_deps \ - -var="bitcoin_network=signet" \ - -var="name_prefix=galoy-sig" -auto-approve - -deploy-signet: - $(TF) apply -var="bitcoin_network=signet" \ - -var="name_prefix=galoy-sig" -auto-approve - -all-signet: create-cluster init deploy-signet-services deploy-signet - - -redeploy-signet-bitcoin: - -kubectl delete namespace galoy-sig-bitcoin --force - cd bitcoin - $(TF) apply -var="bitcoin_network=signet" \ - -var="name_prefix=galoy-sig" -auto-approve - -redeploy-signet-galoy: - -kubectl delete namespace galoy-sig-galoy --force - cd galoy - $(TF) apply -var="bitcoin_network=signet" \ - -var="name_prefix=galoy-sig" -auto-approve - -redeploy-signet-addons: - -kubectl delete namespace galoy-sig-addons --force - cd addons - $(TF) apply -var="name_prefix=galoy-sig" -auto-approve - -redeploy-signet-monitoring: - -kubectl delete namespace galoy-sig-monitoring --force - cd monitoring - $(TF) apply -var="bitcoin_network=signet" \ - -var="name_prefix=galoy-sig" -auto-approve - - run-galoy-smoketest: kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ CHART=galoy ./dev-smoketest-settings.sh && \ ./galoy-smoketest.sh && \ rm -rf smoketest-settings response.json" +run-bitcoin-smoketest: + kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ + CHART=bitcoind ./dev-smoketest-settings.sh && \ + ./bitcoind-smoketest.sh regtest && \ + rm -rf smoketest-settings" + run-kafka-connect-smoketest: kubectl -n galoy-dev-smoketest exec smoketest -- bash -c "cd /charts/ci/tasks && \ CHART=kafka-connect ./dev-smoketest-settings.sh && \ ./kafka-connect-smoketest.sh && \ rm -rf smoketest-settings response.json" -fmt: - cd .. - $(TF) fmt -recursive - -plan: - $(TF) plan -var="bitcoin_network=regtest" -var="name_prefix=galoy-dev" - -review: - $(TF) show -json | jq - -delete: - kubectl delete namespace $(ns) --force - helm-dep-updates: for dir in $$(ls ../charts); do \ cd ../charts/$$dir && helm dependency update && cd -; \ diff --git a/dev/README.md b/dev/README.md index 48a5282584..87100bfb8f 100644 --- a/dev/README.md +++ b/dev/README.md @@ -58,14 +58,6 @@ Currently successfully brings up charts - no guarantee that everything is workin "Beo2lGQZO4nZKzIyZRlVFIQ6jAeo9bNu" ``` -#### Test the web wallet - -1. port forward the web wallet on 3000 - ``` - kubectl -n galoy-dev-addons port-forward --address 0.0.0.0 svc/web-wallet-mobile 3000:80 - ``` -2. open http://localhost:3000 - #### Test the admin panel 1. port forward the web wallet on 3001 diff --git a/dev/Tiltfile b/dev/Tiltfile new file mode 100644 index 0000000000..c965684bfc --- /dev/null +++ b/dev/Tiltfile @@ -0,0 +1,8 @@ +include('./galoy-deps/Tiltfile') +include('./bitcoin/Tiltfile') +include('./monitoring/Tiltfile') +include('./galoy/Tiltfile') +include('./addons/Tiltfile') +include('./stablesats/Tiltfile') +include('./kafka-connect/Tiltfile') +include('./smoketest/Tiltfile') diff --git a/dev/addons/Tiltfile b/dev/addons/Tiltfile new file mode 100644 index 0000000000..b985dd8903 --- /dev/null +++ b/dev/addons/Tiltfile @@ -0,0 +1,108 @@ +load('ext://helm_resource', 'helm_resource') +load('ext://namespace', 'namespace_create') +load('ext://secret', 'secret_from_dict') +load('../common/Tiltfile', 'copy_secret') + +name_prefix = 'galoy-dev' +galoy_namespace = '{}-galoy'.format(name_prefix) +addons_namespace = '{}-addons'.format(name_prefix) +bitcoin_namespace = '{}-bitcoin'.format(name_prefix) +smoketest_namespace = '{}-smoketest'.format(name_prefix) + +namespace_create(addons_namespace) + +## Admin Panel + +k8s_yaml(secret_from_dict( + name='admin-panel', + namespace=addons_namespace, + inputs={ + 'next-auth-secret' : 'dummy123', + 'google-oauth-client-id' : 'dummy', + 'google-oauth-client-secret' : 'dummy', + 'github-oauth-client-id' : 'dummy', + 'github-oauth-client-secret' : 'dummy' + } +)) + +k8s_yaml(helm( + '../../charts/admin-panel', + name='admin-panel', + namespace=addons_namespace, + values = ['./admin-panel-values.yml'] +)) + +k8s_resource(workload='admin-panel', labels='addons') + +k8s_yaml(secret_from_dict( + name='admin-panel-smoketest', + namespace=smoketest_namespace, + inputs={ + 'admin_panel_endpoint' : 'admin-panel.{}.svc.cluster.local'.format(addons_namespace), + 'admin_panel_port' : '3000' + } +)) + + +## Galoy Pay + +k8s_yaml(secret_from_dict( + name='galoy-nostr-private-key', + namespace=addons_namespace, + inputs={ + 'key': 'bb159f7aaafa75a7d4470307c9d6ea18409d4f082b41abcf6346aaae5b2b3b10' + } +)) + +copy_secret( + source_secret_name='lnd1-credentials', + source_namespace=bitcoin_namespace, + target_namespace=addons_namespace, + resource_deps=['bitcoind'], + target_secret_name='lnd-credentials', +) + +copy_secret( + source_secret_name='galoy-redis-pw', + source_namespace=galoy_namespace, + target_namespace=addons_namespace, + resource_deps=['galoy-redis-node'] +) + +k8s_yaml(helm( + '../../charts/galoy-pay', + name='galoy-pay', + namespace=addons_namespace, + values = ['./galoy-pay-values.yml'] +)) + +k8s_resource(workload='galoy-pay', labels='addons') + +k8s_yaml(secret_from_dict( + name='galoy-pay-smoketest', + namespace=smoketest_namespace, + inputs={ + 'galoy_pay_endpoints' : '["galoy-pay.{}.svc.cluster.local"]'.format(addons_namespace), + 'galoy_pay_port' : '80', + 'lnurl_check_disabled' : "true" + } +)) + +## API Dashboard +k8s_yaml(secret_from_dict( + name='api-dashboard', + namespace=addons_namespace, + inputs={ + 'next-auth-secret' : 'dummy123', + 'client-secret' : 'dummy' + } +)) + +k8s_yaml(helm( + '../../charts/api-dashboard', + name = 'api-dashboard', + namespace = addons_namespace, + values = ['./api-dashboard-values.yml'] +)) + +k8s_resource(workload='api-dashboard', labels='addons') diff --git a/dev/addons/admin-panel-values.yml b/dev/addons/admin-panel-values.yml new file mode 100644 index 0000000000..b42ed43549 --- /dev/null +++ b/dev/addons/admin-panel-values.yml @@ -0,0 +1,2 @@ +secrets: + create: false diff --git a/dev/addons/admin-panel.tf b/dev/addons/admin-panel.tf deleted file mode 100644 index e23244f609..0000000000 --- a/dev/addons/admin-panel.tf +++ /dev/null @@ -1,17 +0,0 @@ -resource "helm_release" "admin_panel" { - name = "admin-panel" - chart = "${path.module}/../../charts/admin-panel" - repository = "https://galoymoney.github.io/charts/" - namespace = kubernetes_namespace.addons.metadata[0].name -} - -resource "kubernetes_secret" "admin_panel_smoketest" { - metadata { - name = "admin-panel-smoketest" - namespace = local.smoketest_namespace - } - data = { - admin_panel_endpoint = "admin-panel.${local.addons_namespace}.svc.cluster.local" - admin_panel_port = 3000 - } -} diff --git a/dev/addons/api-dashboard-values.yml b/dev/addons/api-dashboard-values.yml new file mode 100644 index 0000000000..b42ed43549 --- /dev/null +++ b/dev/addons/api-dashboard-values.yml @@ -0,0 +1,2 @@ +secrets: + create: false diff --git a/dev/addons/galoy-pay-values.yml.tmpl b/dev/addons/galoy-pay-values.yml similarity index 100% rename from dev/addons/galoy-pay-values.yml.tmpl rename to dev/addons/galoy-pay-values.yml diff --git a/dev/addons/galoy-pay.tf b/dev/addons/galoy-pay.tf deleted file mode 100644 index c455241a2b..0000000000 --- a/dev/addons/galoy-pay.tf +++ /dev/null @@ -1,63 +0,0 @@ -resource "helm_release" "galoy_pay" { - name = "galoy-pay" - chart = "${path.module}/../../charts/galoy-pay" - namespace = kubernetes_namespace.addons.metadata[0].name - - values = [ - templatefile("${path.module}/galoy-pay-values.yml.tmpl", {}) - ] -} - -resource "kubernetes_secret" "galoy_pay_smoketest" { - metadata { - name = "galoy-pay-smoketest" - namespace = local.smoketest_namespace - } - data = { - galoy_pay_endpoints = jsonencode(["galoy-pay.${local.addons_namespace}.svc.cluster.local"]) - galoy_pay_port = 80 - lnurl_check_disabled = "true" - } -} - -data "kubernetes_secret" "redis_creds" { - metadata { - name = "galoy-redis-pw" - namespace = local.galoy_namespace - } -} -resource "kubernetes_secret" "redis_creds" { - metadata { - name = "galoy-redis-pw" - namespace = kubernetes_namespace.addons.metadata[0].name - } - - data = data.kubernetes_secret.redis_creds.data -} - -resource "kubernetes_secret" "nostr_private_key" { - metadata { - name = "galoy-nostr-private-key" - namespace = kubernetes_namespace.addons.metadata[0].name - } - - data = { - "key" : "bb159f7aaafa75a7d4470307c9d6ea18409d4f082b41abcf6346aaae5b2b3b10" - } -} - -data "kubernetes_secret" "lnd1_credentials" { - metadata { - name = "lnd1-credentials" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "lnd1_credentials" { - metadata { - name = "lnd-credentials" - namespace = kubernetes_namespace.addons.metadata[0].name - } - - data = data.kubernetes_secret.lnd1_credentials.data -} diff --git a/dev/addons/main.tf b/dev/addons/main.tf deleted file mode 100644 index 409e913877..0000000000 --- a/dev/addons/main.tf +++ /dev/null @@ -1,14 +0,0 @@ -variable "name_prefix" {} - -locals { - smoketest_namespace = "${var.name_prefix}-smoketest" - galoy_namespace = "${var.name_prefix}-galoy" - addons_namespace = "${var.name_prefix}-addons" - bitcoin_namespace = "${var.name_prefix}-bitcoin" -} - -resource "kubernetes_namespace" "addons" { - metadata { - name = local.addons_namespace - } -} diff --git a/dev/addons/web-wallet-mobile-values.yml b/dev/addons/web-wallet-mobile-values.yml deleted file mode 100644 index 9371a1598a..0000000000 --- a/dev/addons/web-wallet-mobile-values.yml +++ /dev/null @@ -1,2 +0,0 @@ -mobileLayout: - enabled: true diff --git a/dev/addons/web-wallet.tf b/dev/addons/web-wallet.tf deleted file mode 100644 index 6a2d0995fe..0000000000 --- a/dev/addons/web-wallet.tf +++ /dev/null @@ -1,57 +0,0 @@ -locals { - session_keys = "session_keys" -} - -resource "kubernetes_secret" "web_wallet_secret" { - metadata { - name = "web-wallet" - namespace = kubernetes_namespace.addons.metadata[0].name - } - - data = { - "session-keys" : local.session_keys - } -} - -resource "kubernetes_secret" "web_wallet_mobile_secret" { - metadata { - name = "web-wallet-mobile" - namespace = kubernetes_namespace.addons.metadata[0].name - } - - data = { - "session-keys" : local.session_keys - } -} - -resource "helm_release" "web_wallet" { - name = "web-wallet" - chart = "${path.module}/../../charts/web-wallet" - namespace = kubernetes_namespace.addons.metadata[0].name - - depends_on = [kubernetes_secret.web_wallet_secret] -} - -resource "helm_release" "web_wallet_mobile" { - name = "web-wallet-mobile" - chart = "${path.module}/../../charts/web-wallet" - namespace = kubernetes_namespace.addons.metadata[0].name - - depends_on = [kubernetes_secret.web_wallet_mobile_secret] - - values = [ - file("${path.module}/web-wallet-mobile-values.yml") - ] -} - -resource "kubernetes_secret" "web_wallet_smoketest" { - metadata { - name = "web-wallet-smoketest" - namespace = local.smoketest_namespace - } - data = { - web_wallet_endpoint = "web-wallet.${local.addons_namespace}.svc.cluster.local" - web_wallet_mobile_endpoint = "web-wallet-mobile.${local.addons_namespace}.svc.cluster.local" - web_wallet_port = 80 - } -} diff --git a/dev/bitcoin/Tiltfile b/dev/bitcoin/Tiltfile new file mode 100644 index 0000000000..21c97c5f0e --- /dev/null +++ b/dev/bitcoin/Tiltfile @@ -0,0 +1,200 @@ +load('ext://helm_resource', 'helm_resource') +load('ext://namespace', 'namespace_create') +load('ext://secret', 'secret_from_dict') +load('../common/Tiltfile', 'helm_release') +update_settings(k8s_upsert_timeout_secs=120) + +name_prefix = 'galoy-dev' +bitcoin_network = 'regtest' +bitcoind_rpcpassword = 'rpcpassword' +bitcoin_namespace = '{}-bitcoin'.format(name_prefix) +smoketest_namespace = '{}-smoketest'.format(name_prefix) + +namespace_create(bitcoin_namespace) + +k8s_yaml(secret_from_dict( + name='bitcoind-rpcpassword', + namespace=bitcoin_namespace, + inputs={'password': bitcoind_rpcpassword}, +)) + +helm_release( + "../../charts/bitcoind", + name="bitcoind", + namespace=bitcoin_namespace, + values=['./bitcoind-regtest-values.yml'] +) + +k8s_resource(workload='bitcoind', labels='bitcoin') + +k8s_yaml(secret_from_dict( + name='bitcoind-onchain-rpcpassword', + namespace=bitcoin_namespace, + inputs={'password': bitcoind_rpcpassword}, +)) + +k8s_yaml(secret_from_dict( + name='bitcoind-signer-descriptor', + namespace=bitcoin_namespace, + inputs={ + 'descriptor_json_base64': local( + "base64 bitcoind_signers_descriptors.json | tr -d '\n\r'" + ) + }, +)) + +helm_release( + '../../charts/bitcoind', + name='bitcoind-onchain', + namespace=bitcoin_namespace, + values=['./bitcoind-regtest-values.yml', './bitcoind-onchain-values.yml'] +) + +k8s_resource(workload='bitcoind-onchain', labels='bitcoin') + +local_resource( + name="bitcoind-block-generator", + cmd='./generateBlock.sh', + labels="bitcoin", + resource_deps=["bitcoind-onchain", "bitcoind"] +) + +helm_resource( + name="lnd1", + chart="../../charts/lnd", + namespace=bitcoin_namespace, + flags=[ + '--values=./lnd-regtest-values.yml', + ], + labels='bitcoin' + # resource_deps=["bitcoind-block-generator"], +) + +helm_release( + '../../charts/loop', + name='loop1', + namespace=bitcoin_namespace, + values=['./loop-values.yml'], +) + +k8s_resource(workload='loop1', resource_deps=['lnd1'], labels='bitcoin') + +# TODO: uncomment fulcrum when we actually use it +# helm_resource( +# name="fulcrum", +# chart="../../charts/fulcrum", +# namespace=bitcoin_namespace, +# flags=[ +# '--values=./fulcrum-regtest-values.yml', +# ], +# labels="bitcoin" +# ) + +# k8s_yaml(secret_from_dict( +# name='fulcrum-smoketest', +# namespace=bitcoin_namespace, +# inputs={ +# 'fulcrum_endpoint': 'fulcrum.{}.svc.cluster.local'.format(bitcoin_namespace), +# 'fulcrum_stats_port': 8080 +# }, +# )) + +k8s_yaml(secret_from_dict( + name='bria-smoketest', + namespace=bitcoin_namespace, + inputs={ + 'key': 'value' + }, +)) + +k8s_yaml(secret_from_dict( + name='bria', + namespace=bitcoin_namespace, + inputs={ + 'pg-con': 'postgres://bria:bria@bria-postgresql:5432/bria', + 'signer-encryption-key': local('openssl rand -hex 32'), + }, +)) + +helm_release( + '../../charts/bria', + name='bria', + namespace=bitcoin_namespace, + values=['./bria-values.yml'], + dependency_build=True, + add_repos=True +) + +k8s_resource(workload='bria', labels='bitcoin') + +# TODO: uncomment mempool when we actually use it +helm_resource( + name="mempool", + chart="../../charts/mempool", + namespace=bitcoin_namespace, + flags=[ + '--values=./mempool-regtest-values.yml', + ], + labels="bitcoin" +) + +k8s_yaml(secret_from_dict( + name='mempool-smoketest', + namespace=smoketest_namespace, + inputs={ + 'mempool_endpoint': 'mempool.{}.svc.cluster.local'.format(bitcoin_namespace), + 'mempool_port': 8999 + }, +)) + +k8s_resource(workload='mempool', labels='bitcoin') + +# TODO: uncomment rtl when we actually use it +# helm_resource( +# name="rtl", +# chart="../../charts/rtl", +# namespace=bitcoin_namespace, +# labels="bitcoin" +# ) +# +# k8s_yaml(secret_from_dict( +# name='rtl-smoketest', +# namespace=bitcoin_namespace, +# inputs={ +# 'rtl_endpoint': 'rtl.{}.svc.cluster.local'.format(bitcoin_namespace), +# 'rtl_port': 3000 +# }, +# )) + +# create bitcoind smoketest secret from snippet above +k8s_yaml(secret_from_dict( + name='bitcoind-smoketest', + namespace=smoketest_namespace, + inputs={ + 'bitcoind_rpcpassword': bitcoind_rpcpassword, + 'bitcoind_endpoint': 'bitcoind.{}.svc.cluster.local'.format(bitcoin_namespace), + 'bitcoind_port': '18443', + 'bitcoind_user': 'rpcuser', + 'bitcoind_onchain_rpcpassword': bitcoind_rpcpassword, + 'bitcoind_onchain_endpoint': 'bitcoind.{}.svc.cluster.local'.format(bitcoin_namespace), + } +)) + +# create lnd smoketest secret from snippet above +k8s_yaml(secret_from_dict( + name='lnd-smoketest', + namespace=smoketest_namespace, + inputs={ + 'lnd_api_endpoint': 'lnd1.{}.svc.cluster.local'.format(bitcoin_namespace), + 'lnd_p2p_endpoint': 'lnd1-p2p.{}.svc.cluster.local'.format(bitcoin_namespace), + } +)) + +# create loop smoketest secret from snippet above +k8s_yaml(secret_from_dict( + name='loop-smoketest', + namespace=smoketest_namespace, + inputs={ + 'loop_api_endpoint': 'loop1.{}.svc.cluster.local'.format(bitcoin_namespace), + } +)) diff --git a/dev/bitcoin/bitcoind.tf b/dev/bitcoin/bitcoind.tf deleted file mode 100644 index b0bae11056..0000000000 --- a/dev/bitcoin/bitcoind.tf +++ /dev/null @@ -1,62 +0,0 @@ -resource "kubernetes_secret" "bitcoind" { - metadata { - name = "bitcoind-rpcpassword" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - } - - data = { - password = local.bitcoind_rpcpassword - } -} - -resource "helm_release" "bitcoind" { - name = "bitcoind" - chart = "${path.module}/../../charts/bitcoind" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - - values = [ - file("${path.module}/bitcoind-${var.bitcoin_network}-values.yml") - ] - - depends_on = [ - kubernetes_secret.bitcoind - ] -} - -resource "kubernetes_secret" "bitcoind_signer_descriptor" { - metadata { - name = "bitcoind-signer-descriptor" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - } - - data = { - descriptor_json_base64 = base64encode(file("${path.module}/bitcoind_signers_descriptors.json")) - } -} - -resource "kubernetes_secret" "bitcoind_onchain" { - metadata { - name = "bitcoind-onchain-rpcpassword" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - } - - data = { - password = local.bitcoind_rpcpassword - } -} - -resource "helm_release" "bitcoind_onchain" { - name = "bitcoind-onchain" - chart = "${path.module}/../../charts/bitcoind" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - - values = [ - file("${path.module}/bitcoind-${var.bitcoin_network}-values.yml"), - file("${path.module}/bitcoind-onchain-values.yml") - ] - - depends_on = [ - kubernetes_secret.bitcoind_onchain, - kubernetes_secret.bitcoind_signer_descriptor - ] -} diff --git a/dev/bitcoin/bria.tf b/dev/bitcoin/bria.tf deleted file mode 100644 index 3197cc00ac..0000000000 --- a/dev/bitcoin/bria.tf +++ /dev/null @@ -1,41 +0,0 @@ -resource "random_id" "signer_encryption_key" { - byte_length = 32 -} - -resource "kubernetes_secret" "bria_secrets" { - metadata { - name = "bria" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - } - - data = { - pg-con : "postgres://bria:bria@bria-postgresql:5432/bria" - signer-encryption-key : random_id.signer_encryption_key.hex - } -} - -resource "helm_release" "bria" { - name = "bria" - chart = "${path.module}/../../charts/bria" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - - values = [ - file("${path.module}/bria-values.yml") - ] - - depends_on = [ - helm_release.bitcoind_onchain, - helm_release.fulcrum, - kubernetes_secret.bria_secrets - ] - - dependency_update = true -} - -resource "kubernetes_secret" "bria_smoketest" { - metadata { - name = "bria-smoketest" - namespace = local.smoketest_namespace - } - data = {} -} diff --git a/dev/bitcoin/fulcrum.tf b/dev/bitcoin/fulcrum.tf deleted file mode 100644 index e36a5dfd20..0000000000 --- a/dev/bitcoin/fulcrum.tf +++ /dev/null @@ -1,16 +0,0 @@ -resource "helm_release" "fulcrum" { - name = "fulcrum" - chart = "${path.module}/../../charts/fulcrum" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - - dependency_update = true - timeout = local.bitcoin_network == "regtest" ? 900 : 9000 - values = [ - file("${path.module}/fulcrum-${var.bitcoin_network}-values.yml") - ] - - depends_on = [ - kubernetes_secret.bitcoind_onchain, - helm_release.bitcoind_onchain - ] -} diff --git a/dev/bitcoin/lnd1.tf b/dev/bitcoin/lnd1.tf deleted file mode 100644 index 4818d8d4a0..0000000000 --- a/dev/bitcoin/lnd1.tf +++ /dev/null @@ -1,16 +0,0 @@ -resource "helm_release" "lnd" { - name = "lnd1" - chart = "${path.module}/../../charts/lnd" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - - dependency_update = true - timeout = local.bitcoin_network == "regtest" ? 900 : 9000 - values = [ - file("${path.module}/lnd-${var.bitcoin_network}-values.yml") - ] - - depends_on = [ - kubernetes_secret.bitcoind, - helm_release.bitcoind - ] -} diff --git a/dev/bitcoin/loop1.tf b/dev/bitcoin/loop1.tf deleted file mode 100644 index 6a20622ec5..0000000000 --- a/dev/bitcoin/loop1.tf +++ /dev/null @@ -1,16 +0,0 @@ -resource "helm_release" "loop" { - count = var.bitcoin_network == "signet" ? 0 : 1 - name = "loop1" - chart = "${path.module}/../../charts/loop" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - - dependency_update = true - - values = [ - file("${path.module}/loop-values.yml") - ] - - depends_on = [ - helm_release.lnd - ] -} diff --git a/dev/bitcoin/main.tf b/dev/bitcoin/main.tf deleted file mode 100644 index bd011b3c78..0000000000 --- a/dev/bitcoin/main.tf +++ /dev/null @@ -1,105 +0,0 @@ -variable "name_prefix" {} -variable "bitcoin_network" {} - -locals { - bitcoin_network = var.bitcoin_network - smoketest_namespace = "${var.name_prefix}-smoketest" - bitcoin_namespace = "${var.name_prefix}-bitcoin" - bitcoind_rpcpassword = "rpcpassword" -} - -resource "kubernetes_namespace" "bitcoin" { - metadata { - name = local.bitcoin_namespace - } -} - -resource "null_resource" "bitcoind_block_generator" { - - triggers = { - run_every_time = timestamp() - } - - provisioner "local-exec" { - command = local.bitcoin_network == "regtest" && local.bitcoin_namespace == "galoy-dev-bitcoin" ? "${path.module}/generateBlock.sh" : "echo Running ${local.bitcoin_network}" - interpreter = ["sh", "-c"] - } - - depends_on = [ - helm_release.bitcoind, - helm_release.bitcoind_onchain - ] -} - -resource "kubernetes_secret" "bitcoind_smoketest" { - metadata { - name = "bitcoind-smoketest" - namespace = local.smoketest_namespace - } - - data = { - bitcoind_rpcpassword = local.bitcoind_rpcpassword - bitcoind_endpoint = "bitcoind.${local.bitcoin_namespace}.svc.cluster.local" - bitcoind_port = 18443 - bitcoind_user = "rpcuser" - - bitcoind_onchain_rpcpassword = local.bitcoind_rpcpassword - bitcoind_onchain_endpoint = "bitcoind.${local.bitcoin_namespace}.svc.cluster.local" - } -} - -resource "kubernetes_secret" "fulcrum_smoketest" { - metadata { - name = "fulcrum-smoketest" - namespace = local.smoketest_namespace - } - - data = { - fulcrum_endpoint = "fulcrum.${local.bitcoin_namespace}.svc.cluster.local" - fulcrum_stats_port = 8080 - } -} - -resource "kubernetes_secret" "mempool_smoketest" { - metadata { - name = "mempool-smoketest" - namespace = local.smoketest_namespace - } - data = { - mempool_endpoint = "mempool.${local.bitcoin_namespace}.svc.cluster.local" - mempool_port = 8999 - } -} - -resource "kubernetes_secret" "lnd_smoketest" { - metadata { - name = "lnd-smoketest" - namespace = local.smoketest_namespace - } - data = { - lnd_api_endpoint = "lnd1.${local.bitcoin_namespace}.svc.cluster.local" - lnd_p2p_endpoint = "lnd1-p2p.${local.bitcoin_namespace}.svc.cluster.local" - } -} - -resource "kubernetes_secret" "loop_smoketest" { - count = var.bitcoin_network == "signet" ? 0 : 1 - metadata { - name = "loop-smoketest" - namespace = local.smoketest_namespace - } - data = { - loop_api_endpoint = "loop1.${local.bitcoin_namespace}.svc.cluster.local" - } -} - -resource "kubernetes_secret" "rtl_smoketest" { - metadata { - name = "rtl-smoketest" - namespace = local.smoketest_namespace - } - data = { - rtl_endpoint = "rtl.${local.bitcoin_namespace}.svc.cluster.local" - rtl_port = 3000 - } -} diff --git a/dev/bitcoin/mempool.tf b/dev/bitcoin/mempool.tf deleted file mode 100644 index 0f26991f8d..0000000000 --- a/dev/bitcoin/mempool.tf +++ /dev/null @@ -1,16 +0,0 @@ -resource "helm_release" "mempool" { - name = "mempool" - chart = "${path.module}/../../charts/mempool" - namespace = kubernetes_namespace.bitcoin.metadata[0].name - - dependency_update = true - timeout = local.bitcoin_network == "regtest" ? 900 : 9000 - values = [ - file("${path.module}/mempool-${var.bitcoin_network}-values.yml") - ] - - depends_on = [ - kubernetes_secret.bitcoind_onchain, - helm_release.bitcoind_onchain - ] -} diff --git a/dev/common/Tiltfile b/dev/common/Tiltfile new file mode 100644 index 0000000000..65555e14a3 --- /dev/null +++ b/dev/common/Tiltfile @@ -0,0 +1,42 @@ +load('ext://secret', 'secret_from_dict') + +def wait_for_secret_creation(waiter_name, secret_name, namespace, resource_deps, timeout_secs=30): + local_resource( + name=waiter_name, + cmd='for i in $(seq {}); do kubectl -n {} get secret {} &>/dev/null && echo "Secret exists" && exit 0; sleep 1; done; exit 1'.format(timeout_secs, namespace, secret_name), + resource_deps=resource_deps + ) + +# TODO: Add labels for better grouping +def copy_secret(source_secret_name, source_namespace, target_namespace, resource_deps, target_secret_name=None): + if target_secret_name == None: + target_secret_name = source_secret_name + + random_suffix=local('openssl rand -hex 1') + waiter_name='{}-secret-copier-waiter-{}'.format(target_secret_name, random_suffix) + wait_for_secret_creation(waiter_name, source_secret_name, source_namespace, resource_deps) + + delete_secret_cmd = 'kubectl -n {} delete secret {} --ignore-not-found=true'.format(target_namespace, target_secret_name) + generate_secret_json_cmd = 'kubectl -n {} get secret {} -o json | jq "del(.metadata.namespace, .metadata.name) | .metadata.name = \\"{}\\""'.format(source_namespace, source_secret_name, target_secret_name) + create_secret_cmd = 'kubectl -n {} apply -f -'.format(target_namespace) + + local_resource( + name='{}-secret-copier'.format(target_secret_name), + cmd='{} && {} | {}'.format(delete_secret_cmd, generate_secret_json_cmd, create_secret_cmd), + resource_deps=['{}'.format(waiter_name)] + ) + +def helm_release(pathToChartDir, name, namespace, values=[], dependency_build=False, add_repos=False): + if add_repos and (config.tilt_subcommand == 'up' or config.tilt_subcommand == 'ci'): + local('../common/add-helm-repos.sh {}/Chart.yaml'.format(pathToChartDir)) + + if dependency_build and (config.tilt_subcommand == 'up' or config.tilt_subcommand == 'ci'): + local('helm dependency build {}'.format(pathToChartDir)) + + k8s_yaml(helm( + pathToChartDir, + name, + namespace, + values, + kube_version='1.27.0', + )) diff --git a/dev/common/add-helm-repos.sh b/dev/common/add-helm-repos.sh new file mode 100755 index 0000000000..886fa4b6ff --- /dev/null +++ b/dev/common/add-helm-repos.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +function add_helm_repos() { + yq e '.dependencies[] | select(.repository | test("^oci://") | not) | .name + " " + .repository' "$1" | while read -r name repo; do + helm repo add "$name" "$repo" + done +} + +add_helm_repos "$1" diff --git a/dev/galoy-deps/Tiltfile b/dev/galoy-deps/Tiltfile new file mode 100644 index 0000000000..6e1b7c4720 --- /dev/null +++ b/dev/galoy-deps/Tiltfile @@ -0,0 +1,67 @@ +load('ext://helm_resource', 'helm_resource') +load('ext://namespace', 'namespace_create') +load('../common/Tiltfile', 'copy_secret', 'helm_release') +update_settings(k8s_upsert_timeout_secs=120) + +name_prefix = "galoy-dev" +kafka_namespace = "{}-kafka".format(name_prefix) +ingress_namespace = "{}-ingress".format(name_prefix) +otel_namespace = "{}-otel".format(name_prefix) +kubemonkey_namespace = "{}-kubemonkey".format(name_prefix) + +namespace_create(kafka_namespace) + +# Attaching the namespace to the workload means that the namespace will be deleted when the workload is deleted +# k8s_resource(workload="kafka-operator", objects=["galoy-dev-kafka:namespace"]) + +helm_release( + '../../charts/galoy-deps', + name='kafka', + namespace=kafka_namespace, + values=['./kafka-values.yml'], + dependency_build=True, + add_repos=True +) + +## cert-manager and ingress-nginx + +namespace_create(ingress_namespace) + +# TODO: decide how to label the ingress namespace +# k8s_resource(workload="cert-manager?", objects=["galoy-dev-ingress:namespace"]) + +helm_release( + '../../charts/galoy-deps', + name='cert-manager', + namespace=ingress_namespace, + values=['./cert-manager-values.yml'], +) + +helm_release( + '../../charts/galoy-deps', + name='ingress-nginx', + namespace=ingress_namespace, + values=['./ingress-nginx-values.yml'], +) + +## opentelemetry-collector + +namespace_create(otel_namespace) + +helm_release( + '../../charts/galoy-deps', + name='opentelemetry-collector', + namespace=otel_namespace, + values=['./otel-values.yml'], +) + +# do we need kubemonkey in local dev? + +# helm_resource( +# name="kubemonkey", +# chart="../../charts/galoy-deps", +# namespace=kubemonkey_namespace, +# flags=['--values=./kubemonkey-values.yml'], +# labels="kubemonkey" +# ) + diff --git a/dev/galoy-deps/cert-manager-values.yml.tmpl b/dev/galoy-deps/cert-manager-values.yml similarity index 100% rename from dev/galoy-deps/cert-manager-values.yml.tmpl rename to dev/galoy-deps/cert-manager-values.yml diff --git a/dev/galoy-deps/ingress-values.yml.tmpl b/dev/galoy-deps/ingress-nginx-values.yml similarity index 51% rename from dev/galoy-deps/ingress-values.yml.tmpl rename to dev/galoy-deps/ingress-nginx-values.yml index b7ca6bc2b2..d143f40719 100644 --- a/dev/galoy-deps/ingress-values.yml.tmpl +++ b/dev/galoy-deps/ingress-nginx-values.yml @@ -8,9 +8,11 @@ strimzi-kafka-operator: enabled: false ingress-nginx: controller: + admissionWebhooks: + enabled: false config: - enable-opentracing: ${enable_tracing} - jaeger-service-name: ${service_name} - jaeger-collector-host: ${jaeger_host} + enable-opentracing: true + jaeger-service-name: galoy-dev-ingress + jaeger-collector-host: opentelemetry-collector.galoy-dev-otel.svc.cluster.local service: type: NodePort diff --git a/dev/galoy-deps/ingress.tf b/dev/galoy-deps/ingress.tf index 30bd1802dd..594f8dbfa0 100644 --- a/dev/galoy-deps/ingress.tf +++ b/dev/galoy-deps/ingress.tf @@ -1,52 +1,3 @@ -locals { - letsencrypt_issuer_email = "dev@galoy.io" - ingress_namespace = "${var.name_prefix}-ingress" - ingress_service_name = "${var.name_prefix}-ingress" - jaeger_host = "opentelemetry-collector.${local.otel_namespace}.svc.cluster.local" - enable_tracing = true -} - -resource "kubernetes_namespace" "ingress" { - metadata { - name = local.ingress_namespace - labels = { - type = "ingress-nginx" - } - } -} - -resource "helm_release" "cert_manager" { - name = "cert-manager" - chart = "${path.module}/../../charts/galoy-deps" - namespace = kubernetes_namespace.ingress.metadata[0].name - - values = [ - file("${path.module}/cert-manager-values.yml.tmpl") - ] - - depends_on = [ - helm_release.kafka - ] -} - -resource "helm_release" "ingress_nginx" { - name = "ingress-nginx" - chart = "${path.module}/../../charts/galoy-deps" - namespace = kubernetes_namespace.ingress.metadata[0].name - - values = [ - templatefile("${path.module}/ingress-values.yml.tmpl", { - jaeger_host = local.jaeger_host - service_name = local.ingress_service_name - enable_tracing = local.enable_tracing - }) - ] - - depends_on = [ - helm_release.cert_manager, - ] -} - resource "kubernetes_manifest" "issuer" { manifest = { apiVersion = "cert-manager.io/v1" @@ -57,7 +8,7 @@ resource "kubernetes_manifest" "issuer" { spec = { acme = { server = "https://acme-v02.api.letsencrypt.org/directory" - email = local.letsencrypt_issuer_email + email = "dev@galoy.io" privateKeySecretRef = { name = "letsencrypt-issuer" } diff --git a/dev/galoy-deps/kafka-values.yml.tmpl b/dev/galoy-deps/kafka-values.yml similarity index 68% rename from dev/galoy-deps/kafka-values.yml.tmpl rename to dev/galoy-deps/kafka-values.yml index 2e6e98e734..69fbcf4129 100644 --- a/dev/galoy-deps/kafka-values.yml.tmpl +++ b/dev/galoy-deps/kafka-values.yml @@ -7,10 +7,6 @@ kubemonkey: opentelemetry-collector: enabled: false strimzi-kafka-operator: - watchNamespaces: -%{ for namespace in watch_namespaces ~} - - "${namespace}" -%{ endfor ~} kafka: listener: type: nodeport diff --git a/dev/galoy-deps/kafka.tf b/dev/galoy-deps/kafka.tf deleted file mode 100644 index c84421ff31..0000000000 --- a/dev/galoy-deps/kafka.tf +++ /dev/null @@ -1,28 +0,0 @@ -variable "watch_namespaces" { - default = [] -} - -resource "kubernetes_namespace" "kafka" { - metadata { - name = local.kafka_namespace - } -} - -locals { - watch_namespaces = var.watch_namespaces - kafka_namespace = "${var.name_prefix}-kafka" -} - -resource "helm_release" "kafka" { - name = "kafka" - chart = "${path.module}/../../charts/galoy-deps" - namespace = kubernetes_namespace.kafka.metadata[0].name - - values = [ - templatefile("${path.module}/kafka-values.yml.tmpl", { - watch_namespaces : local.watch_namespaces - }) - ] - - dependency_update = true -} diff --git a/dev/galoy-deps/kubemonkey.tf b/dev/galoy-deps/kubemonkey.tf deleted file mode 100644 index c224fc54f5..0000000000 --- a/dev/galoy-deps/kubemonkey.tf +++ /dev/null @@ -1,38 +0,0 @@ -resource "kubernetes_namespace" "kubemonkey" { - metadata { - name = local.kubemonkey_namespace - } -} - -locals { - ns1 = "test" - ns2 = "test2" - - kubemonkey_namespace = "${var.name_prefix}-kubemonkey" - kubemonkey_time_zone = "Etc/UTC" - kubemonkey_notification_url = "dummy" - kubemonkey_whitelisted_namespaces = [ - local.ns1, - local.ns2 - ] -} - -resource "helm_release" "kubemonkey" { - name = "kubemonkey" - chart = "${path.module}/../../charts/galoy-deps" - namespace = kubernetes_namespace.kubemonkey.metadata[0].name - - values = [ - templatefile("${path.module}/kubemonkey-values.yml.tmpl", { - time_zone : local.kubemonkey_time_zone - whitelisted_namespaces : local.kubemonkey_whitelisted_namespaces - notification_url : local.kubemonkey_notification_url - }) - ] - - dependency_update = true - - depends_on = [ - helm_release.otel - ] -} diff --git a/dev/galoy-deps/main.tf b/dev/galoy-deps/main.tf deleted file mode 100644 index c5d8e2e47c..0000000000 --- a/dev/galoy-deps/main.tf +++ /dev/null @@ -1 +0,0 @@ -variable "name_prefix" {} diff --git a/dev/galoy-deps/otel.tf b/dev/galoy-deps/otel.tf deleted file mode 100644 index 48c04b7ac5..0000000000 --- a/dev/galoy-deps/otel.tf +++ /dev/null @@ -1,25 +0,0 @@ -locals { - otel_namespace = "${var.name_prefix}-otel" -} - -resource "kubernetes_namespace" "otel" { - metadata { - name = local.otel_namespace - } -} - -resource "helm_release" "otel" { - name = "opentelemetry-collector" - chart = "${path.module}/../../charts/galoy-deps" - namespace = kubernetes_namespace.otel.metadata[0].name - - values = [ - file("${path.module}/otel-values.yml") - ] - - dependency_update = true - - depends_on = [ - helm_release.kafka - ] -} diff --git a/dev/galoy/Tiltfile b/dev/galoy/Tiltfile new file mode 100644 index 0000000000..b3ca731b77 --- /dev/null +++ b/dev/galoy/Tiltfile @@ -0,0 +1,220 @@ +load('ext://helm_resource', 'helm_resource') +load('ext://namespace', 'namespace_create') +load('ext://secret', 'secret_from_dict') +load('../common/Tiltfile', 'copy_secret', 'helm_release') +update_settings(k8s_upsert_timeout_secs=120) + +name_prefix = 'galoy-dev' +galoy_namespace = '{}-galoy'.format(name_prefix) +bitcoin_namespace = '{}-bitcoin'.format(name_prefix) +smoketest_namespace = '{}-smoketest'.format(name_prefix) + +namespace_create(galoy_namespace) + +copy_secret( + source_secret_name='network', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + resource_deps=['bitcoind'] +) + +copy_secret( + source_secret_name='bitcoind-rpcpassword', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + resource_deps=['bitcoind'] +) + +copy_secret( + source_secret_name='lnd1-pubkey', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + resource_deps=['lnd1'] +) + +copy_secret( + source_secret_name='lnd1-pubkey', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + target_secret_name='lnd2-pubkey', + resource_deps=['lnd1'] +) + +copy_secret( + source_secret_name='lnd1-credentials', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + resource_deps=['lnd1'] +) + +copy_secret( + source_secret_name='lnd1-credentials', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + target_secret_name='lnd2-credentials', + resource_deps=['lnd1'] +) + +copy_secret( + source_secret_name='loop1-credentials', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + resource_deps=['loop1'] +) + +copy_secret( + source_secret_name='loop1-credentials', + source_namespace=bitcoin_namespace, + target_namespace=galoy_namespace, + target_secret_name='loop2-credentials', + resource_deps=['loop1'] +) + +k8s_yaml(secret_from_dict( + name='gcs-sa-key', + namespace=galoy_namespace, + inputs={'key': 'dummy'} +)) + +k8s_yaml(secret_from_dict( + name='bria-api-key', + namespace=galoy_namespace, + inputs={'api-key': 'bria_dev_000000000000000000000'} +)) + +k8s_yaml(secret_from_dict( + name='geetest-key', + namespace=galoy_namespace, + inputs={'key': 'dummy', 'id': 'dummy'} +)) + +k8s_yaml(secret_from_dict( + name='galoy-mongodb', + namespace=galoy_namespace, + inputs={ + 'mongodb-password' : 'password', + 'mongodb-passwords' : 'password', + 'mongodb-root-password' : 'password', + 'mongodb-replica-set-key' : 'replica' + } +)) + +k8s_yaml(secret_from_dict( + name='galoy-mongodb-connection-string', + namespace=galoy_namespace, + inputs={ + 'mongodb-con' : 'mongodb://testGaloy:password@galoy-mongodb:27017/galoy' + } +)) + +# galoy-redis-pw secret +k8s_yaml(secret_from_dict( + name='galoy-redis-pw', + namespace=galoy_namespace, + inputs={'redis-password': 'redispw'} +)) + +# twilio-secret secret +k8s_yaml(secret_from_dict( + name='twilio-secret', + namespace=galoy_namespace, + inputs={ + 'TWILIO_VERIFY_SERVICE_ID' : 'dummy', + 'TWILIO_ACCOUNT_SID' : 'ACdummy', + 'TWILIO_AUTH_TOKEN' : 'dummy' + } +)) + +# svix-secret secret +k8s_yaml(secret_from_dict( + name='svix-secret', + namespace=galoy_namespace, + inputs={ + 'svix-secret': 'dummy' + } +)) + +# proxy-check-api-key secret +k8s_yaml(secret_from_dict( + name='proxy-check-api-key', + namespace=galoy_namespace, + inputs={ + 'api-key': 'dummy' + } +)) + +# kratos-secret secret +k8s_yaml(secret_from_dict( + name='kratos-secret', + namespace=galoy_namespace, + inputs={ + 'master_user_password': 'dummy', + 'callback_api_key': 'dummy', + } +)) + +# galoy-oathkeeper secret +k8s_yaml(secret_from_dict( + name='galoy-oathkeeper', + namespace=galoy_namespace, + inputs={ + 'mutator.id_token.jwks.json': local( + "cat oathkeeper_mutator_id_token_jwks.json | jq -c" + ) + } +)) + +local('helm repo add bitnami https://charts.bitnami.com/bitnami') + +helm_resource( + name='postgresql', + chart='bitnami/postgresql', + namespace=galoy_namespace, + flags=[ + '--values=./postgresql-values.yml', + ], + labels='galoy' +) + +k8s_yaml(secret_from_dict( + name='galoy-price-history-postgres-creds', + namespace=galoy_namespace, + inputs={ + 'username': 'price-history', + 'password': 'price-history', + 'database': 'price-history' + } +)) + +k8s_yaml(secret_from_dict( + name='api-keys', + namespace=galoy_namespace, + inputs={'pg-con': 'postgres://api-keys:api-keys@api-keys-postgresql:5432/api-keys'} +)) + +helm_release( + '../../charts/galoy', + name='galoy', + namespace=galoy_namespace, + values=['./galoy-values.yml', './galoy-regtest-values.yml'], + dependency_build=True, + add_repos=True +) + +k8s_resource(workload='galoy-cronjob', pod_readiness='ignore') +k8s_resource(workload='galoy-price-history-cronjob', pod_readiness='ignore') +k8s_resource(workload='galoy-price-history-postgres-migrate-1', pod_readiness='ignore') +k8s_resource(workload='galoy-mongo-backup', pod_readiness='ignore') + +k8s_resource(workload='api-keys', pod_readiness='ignore') + +k8s_yaml(secret_from_dict( + name='galoy-smoketest', + namespace=smoketest_namespace, + inputs={ + 'galoy_endpoint' : 'galoy-oathkeeper-proxy.{}.svc.cluster.local'.format(galoy_namespace), + 'galoy_port' : '4455', + 'price_history_endpoint' : 'galoy-price-history.{}.svc.cluster.local'.format(galoy_namespace), + 'price_history_port' : '50052', + } +)) diff --git a/dev/galoy/galoy-regtest-values.yml b/dev/galoy/galoy-regtest-values.yml index 84c9369b63..d0bd3dcc78 100644 --- a/dev/galoy/galoy-regtest-values.yml +++ b/dev/galoy/galoy-regtest-values.yml @@ -63,6 +63,11 @@ mongodb: metrics: enabled: false initDbScripts: {} + customReadinessProbe: + timeoutSeconds: 7 + exec: + command: + - /bitnami/scripts/readiness-probe.sh redis: replica: @@ -92,5 +97,8 @@ oathkeeper: kratos: replicaCount: 1 +hydra: + replicaCount: 1 + secrets: create: false diff --git a/dev/galoy/galoy-values.yml.tmpl b/dev/galoy/galoy-values.yml similarity index 91% rename from dev/galoy/galoy-values.yml.tmpl rename to dev/galoy/galoy-values.yml index e379835f2d..28598a4e71 100644 --- a/dev/galoy/galoy-values.yml.tmpl +++ b/dev/galoy/galoy-values.yml @@ -4,7 +4,9 @@ galoy: kratos: kratos: config: - dsn: postgresql://kratos-pg:kratos-pg@${kratos_pg_host}/kratos-pg + log: + level: warning + dsn: postgresql://kratos-pg:kratos-pg@postgresql.galoy-dev-galoy.svc.cluster.local/kratos-pg selfservice: flows: settings: @@ -20,7 +22,7 @@ kratos: type: api_key config: name: Authorization - value: ${kratos_callback_api_key} + value: dummy in: header registration: after: @@ -37,6 +39,6 @@ kratos: type: api_key config: name: Authorization - value: ${kratos_callback_api_key} + value: dummy in: header - hook: session diff --git a/dev/galoy/main.tf b/dev/galoy/main.tf deleted file mode 100644 index 4971363ccf..0000000000 --- a/dev/galoy/main.tf +++ /dev/null @@ -1,377 +0,0 @@ -variable "name_prefix" {} -variable "bitcoin_network" {} - -locals { - bitcoin_network = var.bitcoin_network - smoketest_namespace = "${var.name_prefix}-smoketest" - galoy_namespace = "${var.name_prefix}-galoy" - bitcoin_namespace = "${var.name_prefix}-bitcoin" - bitcoin_secret = "bitcoind-rpcpassword" - - postgres_database = "price-history" - postgres_username = "price-history" - postgres_password = "price-history" - - galoy-oathkeeper-proxy-host = "galoy-oathkeeper-proxy.${local.galoy_namespace}.svc.cluster.local" - kratos_pg_host = "postgresql.${local.galoy_namespace}.svc.cluster.local" -} - -resource "kubernetes_namespace" "galoy" { - metadata { - name = local.galoy_namespace - } -} - -data "kubernetes_secret" "network" { - metadata { - name = "network" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "network" { - metadata { - name = "network" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.network.data -} - -resource "kubernetes_secret" "bria" { - metadata { - name = "bria-api-key" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - api-key = "bria_dev_000000000000000000000" - } -} - -resource "kubernetes_secret" "gcs_sa_key" { - metadata { - name = "gcs-sa-key" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = {} -} - -resource "kubernetes_secret" "geetest_key" { - metadata { - name = "geetest-key" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - key = "dummy" - id = "dummy" - } -} - -resource "kubernetes_secret" "mongodb_creds" { - metadata { - name = "galoy-mongodb" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - "mongodb-password" : "password" - "mongodb-passwords" : "password" - "mongodb-root-password" : "password" - "mongodb-replica-set-key" : "replica" - } -} - -resource "kubernetes_secret" "mongodb_connection_string" { - metadata { - name = "galoy-mongodb-connection-string" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - "mongodb-con" : "mongodb://testGaloy:password@galoy-mongodb:27017/galoy" - } -} - -resource "kubernetes_secret" "redis_creds" { - metadata { - name = "galoy-redis-pw" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - "redis-password" : "password" - } -} - -resource "kubernetes_secret" "dropbox_access_token" { - metadata { - name = "dropbox-access-token" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - token = "dummy" - } -} - -resource "kubernetes_secret" "twilio_secret" { - metadata { - name = "twilio-secret" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - TWILIO_VERIFY_SERVICE_ID = "dummy" - TWILIO_ACCOUNT_SID = "ACdummy" - TWILIO_AUTH_TOKEN = "dummy" - } -} - -data "kubernetes_secret" "bitcoin_rpcpassword" { - metadata { - name = local.bitcoin_secret - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "bitcoinrpc_password" { - metadata { - name = "bitcoind-rpcpassword" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.bitcoin_rpcpassword.data -} - -data "kubernetes_secret" "lnd2_pubkey" { - metadata { - name = "lnd1-pubkey" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "lnd2_pubkey" { - metadata { - name = "lnd2-pubkey" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.lnd2_pubkey.data -} - -data "kubernetes_secret" "lnd1_pubkey" { - metadata { - name = "lnd1-pubkey" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "lnd1_pubkey" { - metadata { - name = "lnd1-pubkey" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.lnd1_pubkey.data -} - -data "kubernetes_secret" "lnd2_credentials" { - metadata { - name = "lnd1-credentials" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "lnd2_credentials" { - metadata { - name = "lnd2-credentials" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.lnd2_credentials.data -} - -data "kubernetes_secret" "loop2_credentials" { - metadata { - name = "loop1-credentials" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "loop2_credentials" { - metadata { - name = "loop2-credentials" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.loop2_credentials.data -} - -data "kubernetes_secret" "lnd1_credentials" { - metadata { - name = "lnd1-credentials" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "lnd1_credentials" { - metadata { - name = "lnd1-credentials" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.lnd1_credentials.data -} - -data "kubernetes_secret" "loop1_credentials" { - metadata { - name = "loop1-credentials" - namespace = local.bitcoin_namespace - } -} - -resource "kubernetes_secret" "loop1_credentials" { - metadata { - name = "loop1-credentials" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = data.kubernetes_secret.loop1_credentials.data -} - -resource "jose_keyset" "oathkeeper" {} - -resource "kubernetes_secret" "oathkeeper" { - metadata { - name = "galoy-oathkeeper" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - "mutator.id_token.jwks.json" = jsonencode({ - keys = [jsondecode(jose_keyset.oathkeeper.private_key)] - }) - } -} - - -resource "helm_release" "postgresql" { - name = "postgresql" - repository = "https://charts.bitnami.com/bitnami" - chart = "postgresql" - namespace = kubernetes_namespace.galoy.metadata[0].name - - values = [ - file("${path.module}/postgresql-values.yml") - ] -} - -resource "random_password" "kratos_callback_api_key" { - length = 32 - special = false -} - -resource "kubernetes_secret" "kratos_master_user_password" { - metadata { - name = "kratos-secret" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - "master_user_password" = random_password.kratos_master_user_password.result - "callback_api_key" = random_password.kratos_callback_api_key.result - } -} - -resource "kubernetes_secret" "svix_secret" { - metadata { - name = "svix-secret" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - data = { - "svix-secret" = "dummy" - } -} - -resource "kubernetes_secret" "proxy_check_api_key" { - metadata { - name = "proxy-check-api-key" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - data = { - "api-key" = "dummy" - } -} - -resource "helm_release" "galoy" { - name = "galoy" - chart = "${path.module}/../../charts/galoy" - namespace = kubernetes_namespace.galoy.metadata[0].name - - values = [ - templatefile("${path.module}/galoy-values.yml.tmpl", { - kratos_pg_host : local.kratos_pg_host, - kratos_callback_api_key : random_password.kratos_callback_api_key.result - }), - file("${path.module}/galoy-${var.bitcoin_network}-values.yml") - ] - - depends_on = [ - kubernetes_secret.bitcoinrpc_password, - kubernetes_secret.lnd1_credentials, - kubernetes_secret.loop1_credentials, - kubernetes_secret.lnd1_pubkey, - kubernetes_secret.lnd2_credentials, - kubernetes_secret.loop2_credentials, - kubernetes_secret.lnd2_pubkey, - kubernetes_secret.price_history_postgres_creds, - kubernetes_secret.kratos_master_user_password, - helm_release.postgresql - ] - - dependency_update = true - timeout = 900 -} - -resource "kubernetes_secret" "price_history_postgres_creds" { - metadata { - name = "galoy-price-history-postgres-creds" - namespace = kubernetes_namespace.galoy.metadata[0].name - } - - data = { - username = local.postgres_username - password = local.postgres_password - database = local.postgres_database - } -} - -resource "random_password" "kratos_master_user_password" { - length = 32 - special = false -} - -resource "kubernetes_secret" "smoketest" { - metadata { - name = "galoy-smoketest" - namespace = local.smoketest_namespace - } - data = { - galoy_endpoint = local.galoy-oathkeeper-proxy-host - galoy_port = 4455 - price_history_endpoint = "galoy-price-history.${local.galoy_namespace}.svc.cluster.local" - price_history_port = 50052 - } -} - -terraform { - required_providers { - jose = { - source = "bluemill/jose" - version = "1.0.0" - } - } -} diff --git a/dev/galoy/oathkeeper_mutator_id_token_jwks.json b/dev/galoy/oathkeeper_mutator_id_token_jwks.json new file mode 100644 index 0000000000..2441adc010 --- /dev/null +++ b/dev/galoy/oathkeeper_mutator_id_token_jwks.json @@ -0,0 +1,18 @@ +{ + "keys": [ + { + "alg": "RS256", + "d": "WABQlnmXZ1n_prLInVVVh0lY52KlY7MxtqLKPoWZCV1Rt5nWwLhp9xMXhcYHcmck3aSMHD26Wkt1fbbtoNSB5hywmfD9nnxPc1EjbkkLNyQ8V4pcX5NpZhcLhRz8ODgIYWr4wNoXNTbVhHSMQMVUYTdA4FfAokjIXcYCCcjwlcXe-GxzIgDj0T5PjmWty6KDbbj3i8Dtas-npjgbhkS7_vJAnrMOB5baEm-j9BkWRnDkZMh_jpagXJ-lWc_d_f6-7-YcQK1Twg0wn34BVL2bbN9ekqbYdnw8LqfuVv2jjEHPOCHCpF8HvRR-xfxeXgjmFj-PE3MKV5qg3DHUL9-WsD2wMBXIKXr6D37MJnCa4j40W2747ORB_llP0XeDlTXlOSB8H87W3T2TVSWlsUlLE5Kx67GNIPfpbXnvck6GewqhZPdzQESONoe7gxlQWAq7v4b_k1BvFJLg0O6IK1m0Hb5k2Grb_1TZfsdZ-NOK9aEraOzCHfrQ0Nnvg191edCEfl2YXF--SHonv73lKhGT_D8iaf3gBSzmuEVPHh_U4Y1B9uqZpYP9Ei0PHkzifvJ5fAaL3XHxKXJVU60glSnC2ouFYIpQpEDFVWaPuDxfVg7iEuaZqpsw1AGZb4nrHhMPbjIs-7MwOich_iN8YiE27DwPE-nSw4y2LEOu1ukWDg0", + "dp": "HTpfnqsgU15rfde7Isw6H8zRqoEUxDM0N-Zo8iKrCUWq6wd8x-xBnoSv_r5lH0a6abGDwh4CHP5QZzxThn2C0ijBaEDXfqqVnX9z_68nNHuABOT9Aju6qRLPCy-djZoj86ui32F_3PShKFLnLCd3eeodVghhNYa6WSEZwC0MdjHs6vSA-eV8vP8JaOfuL2l81ilVr7-vo0HHgyaN1eHAqd8nau0qhDvgnVsWwWGAANvbODaL7b1YZh2ZdR-i0hfIRRESVzlCeEowqJtqZ8t1o0BDCFwdjvkp-T558Vm4R2rdzqoRBIWGzzdExhH-AraBLQUHGvIR0-7XIfqaY76aOQ", + "dq": "MwxEH6L5gokAP1U04_kz9HhWdUUfzpyPcB9JRNTUhVgrZIYg5awFRZKPou18sxmMzeJ29Er9Q_Ro3huCcOqZTHv5VMWj2jPCxgie6__98QKTS4vieLTXwX3Nfx6KA5EXuKnle1MuPylvQk8O11wcC2JqCML02DDlJ92YR125AIEx3FA3GFNXul1myhQBeXp3Z-Yv1DQ3_s2ev3ZQK9Z5jAoMZmOPLe7BFsZWE-tYOTb97f9BQRfQca7TmCiRXZo6OaiE90dgHVQuggp8FV4VpwIHePj3NhRUflBLbMKQY4WBxZilLVtcHzkXunzk4_uIYdQkzZwqhmcIukvk4DBbBQ", + "e": "AQAB", + "kid": "VAu6VmE6y-qU7M3Bhn1_nuj7oTwzL-GyuETHGfB6TtY=", + "kty": "RSA", + "n": "xG2w1oHymSvJfpz0TwvkPnQWStKtKdAcIEy8PP9BSbSJj0sv_F2Yo9KdJGpiDuW0qCaEw1uL5bgZ0ZDladvxwittVWq-VQ_7QOsf2H1J02fvbo4RQ17GnZeK2iwlvx1zD3z0RXabEimCUUMZaPuAlaaLGaXw1ETVdvCXgBmeqrAmEedkFwS7nh7-lcBwl4FAcc3yP2RAzDWgTHJN85qQnIJUHLwyxJZdoum1cylbknJU2dgxGQQ8rZQyjF6v6hG-H95YhcyCU7GWNYFsjMkzxOjCRy1f-2_zHvrSIxpK6cUAmeHfq8Dx3gzQ006xR3soWmDqQTgxRKvE8cAXuww83UcSt1Eb4HPgAhvs3xqD-bdLZB3VtcAjtNtzrW8tgSTQuTrc6BD_ddsnt2mUt2K3SIdSmuabedXaABV9IwaXg9gxqtyFZtxu-bQdq-vEWeGXgBIE_JioKIskcoCfV8g67hMK0c05sBrdh6aDurb_Q41fXqRLkU-jdWUP6RiRz1zW1fFDSRdsc8Yik4FpXZO-j2bv0toh8Ti7k0i9ylwPUGCrZcCHLmCU0E9pmz_6lkz4XR_vQULLvLzSRzgW_aH-o8dk9GBiS1hW2JnsEeFet4D6Dmhtkm2cWuEgNWNLE-Re-woLlQ6IpkRnKSo28FT6XW48vPKxGsRzclTcaIHSPpU", + "p": "-6T0mbghT7sVzUIVm-R0GHKqBCDMp53PrPPJZsOA31WQXj99OPBQADZMQZgCEvaBbTs9VKzfJHhyQ2vY0EdXkHcKH43qMMSMtx-p4BbU8J7j5c02uaslJ95fceWody2n8oiguUCuSq15GqNLtJ7cZcEEcbsZFezkr84Nw7FTHFSWBjxmL00JXZ8Wu5J3b4J_P5GM4i6GWreVn1ivTMyygFSGU0pOVx4peZmhcfNmuLKEPWcM7Ilr3tb0qDE76-isFdaL6lQADVcRt35rdV43HJVDr8t3KHLqbCw7L1dcdN98fJC80yeHFmakTKMuTNSt7JFs1FGurhjbCIiOAJJLUw", + "q": "x9QSaKMUXCaTWRtfxQJajDD5wVy1tnyuwTI0uYqGiCkc-LbW7PYqxxWzci3OSHO4TsR4WdFbJeqa9zqSjepSIOzqBerJKhrtR-NzhE-K03NEcaEa4_IvIbHBoJXeNXF6Ym_W-lo9gVNPqV3ff3q3LVRGQ6l6Z-Hd8YvaRtuk1tcGqMgt4YREWIVaqsAL8xf1hBtlqOdifSpRfIO9m_oWm5gHWKfq-4i3VJxogHcWbMxF7NARIZCFufTjRKiXC8SL4RfdAukVwSDfduLzAB_5OkDfDFTGhbJM7ElsPrkZM2AzDs7WGl6kgh0JYdcxxRshsPwYXrIr5L6x0qBMBw15dw", + "qi": "zm1XgPMkeTjOQgD3piw046-P3eG1bgQKBCO70V9QH-3wRtGtYF-5VVrpOuSwVjs0hYWGqgWADOAwNJXKQqIiokguXyTtRxLTuLuDRBoFQp4J_RJJI9CkWr8GRMlH_2pctqstVLrcCVgWkUAa_uZ2UZGqNP5tdP8GGb_q4EZ91Te28xy88x044Vn013u861LvNLslWQbPTmh82seBpnsP_GDd3tdESWTwK278HeqqN8bkgrRlf1Kd_QUGevyoj6MDxOv8E_6GFPcZlDi8xxQsQ3-C3Q-Yged40_1QZpQB0jUSsmOV0HomQwqsFolk95VeGqgj49mhGRQ21rynhS9Q0Q", + "use": "sig" + } + ] +} diff --git a/dev/kafka-connect/Tiltfile b/dev/kafka-connect/Tiltfile new file mode 100644 index 0000000000..a7f0d6f13f --- /dev/null +++ b/dev/kafka-connect/Tiltfile @@ -0,0 +1,21 @@ +load('ext://namespace', 'namespace_create') +load('ext://secret', 'secret_from_dict') + +name_prefix = 'galoy-dev' +kafka_namespace = '{}-kafka'.format(name_prefix) +smoketest_namespace = '{}-smoketest'.format(name_prefix) + +k8s_yaml(helm( + '../../charts/kafka-connect', + name='kafka-connect', + namespace=kafka_namespace, +)) + +k8s_yaml(secret_from_dict( + name = 'kafka-connect-smoketest', + namespace = smoketest_namespace, + inputs={ + 'kafka_connect_api_host' : 'kafka-connect-api.{}.svc.cluster.local'.format(kafka_namespace), + 'kafka_connect_api_port' : '8083' + } +)) diff --git a/dev/kafka-connect/main.tf b/dev/kafka-connect/main.tf deleted file mode 100644 index 46a2254ddc..0000000000 --- a/dev/kafka-connect/main.tf +++ /dev/null @@ -1,33 +0,0 @@ -variable "name_prefix" { - default = "galoy-dev" -} - -locals { - kafka_namespace = "${var.name_prefix}-kafka" - smoketest_namespace = "${var.name_prefix}-smoketest" -} - -resource "kubernetes_secret" "kafka_connect_smoketest" { - metadata { - name = "kafka-connect-smoketest" - namespace = local.smoketest_namespace - } - data = { - kafka_connect_api_host = "kafka-connect-api.${local.kafka_namespace}.svc.cluster.local" - kafka_connect_api_port = 8083 - } -} - -resource "helm_release" "kafka_connect" { - name = "kafka-connect" - chart = "${path.module}/../../charts/kafka-connect" - namespace = local.kafka_namespace - - values = [ - templatefile("${path.module}/kafka-values.yml.tmpl", { - allowed_namespace = local.smoketest_namespace - }) - ] - - dependency_update = true -} diff --git a/dev/main.tf b/dev/main.tf deleted file mode 100644 index 04bc091a0e..0000000000 --- a/dev/main.tf +++ /dev/null @@ -1,82 +0,0 @@ -variable "bitcoin_network" {} -variable "name_prefix" {} - -locals { - bitcoin_network = var.bitcoin_network - name_prefix = var.name_prefix -} - -module "galoy_deps" { - source = "./galoy-deps" - - name_prefix = local.name_prefix -} - -module "infra_services" { - source = "git::https://github.com/GaloyMoney/galoy-infra.git//modules/smoketest/gcp?ref=13b2ef9" - - name_prefix = local.name_prefix - cluster_endpoint = "dummy" - cluster_ca_cert = "dummy" -} - -module "kafka_connect" { - source = "./kafka-connect" - - name_prefix = local.name_prefix - - depends_on = [ - module.galoy_deps, - module.infra_services - ] -} - -module "bitcoin" { - source = "./bitcoin" - - bitcoin_network = local.bitcoin_network - name_prefix = local.name_prefix - - depends_on = [ - module.galoy_deps - ] -} - -module "galoy" { - source = "./galoy" - - bitcoin_network = local.bitcoin_network - name_prefix = local.name_prefix - - depends_on = [ - module.bitcoin - ] -} - -module "monitoring" { - source = "./monitoring" - - name_prefix = local.name_prefix -} - -module "addons" { - source = "./addons" - - name_prefix = local.name_prefix - - depends_on = [ - module.galoy - ] -} - -module "smoketest" { - source = "./smoketest" - - name_prefix = local.name_prefix -} - -provider "kubernetes" { - experiments { - manifest_resource = true - } -} diff --git a/dev/monitoring/Tiltfile b/dev/monitoring/Tiltfile new file mode 100644 index 0000000000..553abcb674 --- /dev/null +++ b/dev/monitoring/Tiltfile @@ -0,0 +1,25 @@ +load('ext://namespace', 'namespace_create') +load('ext://helm_resource', 'helm_resource') +load('ext://secret', 'secret_from_dict') + +name_prefix = 'galoy-dev' +monitoring_namespace = '{}-monitoring'.format(name_prefix) +smoketest_namespace = '{}-smoketest'.format(name_prefix) + +namespace_create(monitoring_namespace) + +helm_resource( + name='monitoring', + chart='../../charts/monitoring', + namespace=monitoring_namespace, + labels='monitoring', + update_dependencies=True +) + +k8s_yaml(secret_from_dict( + name = 'monitoring-smoketest', + namespace = smoketest_namespace, + inputs={ + 'grafana_host': 'monitoring-grafana.{}.svc.cluster.local'.format(monitoring_namespace), + } +)) diff --git a/dev/monitoring/main.tf b/dev/monitoring/main.tf deleted file mode 100644 index 9498012032..0000000000 --- a/dev/monitoring/main.tf +++ /dev/null @@ -1,34 +0,0 @@ -variable "name_prefix" {} - -locals { - smoketest_namespace = "${var.name_prefix}-smoketest" - monitoring_namespace = "${var.name_prefix}-monitoring" -} - -resource "kubernetes_namespace" "monitoring" { - metadata { - name = local.monitoring_namespace - } -} - -resource "helm_release" "monitoring" { - name = "monitoring" - chart = "${path.module}/../../charts/monitoring" - namespace = kubernetes_namespace.monitoring.metadata[0].name - - values = [ - file("${path.module}/monitoring-values.yml") - ] - - dependency_update = true -} - -resource "kubernetes_secret" "monitoring_smoketest" { - metadata { - name = "monitoring-smoketest" - namespace = local.smoketest_namespace - } - data = { - grafana_host = "monitoring-grafana.${local.monitoring_namespace}.svc.cluster.local" - } -} diff --git a/dev/monitoring/monitoring-values.yml b/dev/monitoring/monitoring-values.yml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dev/smoketest/Tiltfile b/dev/smoketest/Tiltfile new file mode 100644 index 0000000000..4b8570066d --- /dev/null +++ b/dev/smoketest/Tiltfile @@ -0,0 +1,104 @@ +load('ext://namespace', 'namespace_create') +load('ext://secret', 'secret_from_dict') + +name_prefix = 'galoy-dev' +smoketest_namespace = '{}-smoketest'.format(name_prefix) + +namespace_create(smoketest_namespace) + +smoketest_role_yaml=""" +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: smoketest + namespace: galoy-dev-smoketest +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +""" +k8s_yaml(blob(smoketest_role_yaml)) + +smoketest_serviceaccount_yaml=""" +apiVersion: v1 +kind: ServiceAccount +metadata: + name: smoketest + namespace: galoy-dev-smoketest +""" +k8s_yaml(blob(smoketest_serviceaccount_yaml)) + +smoketest_rolebinding_yaml=""" +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: smoketest + namespace: galoy-dev-smoketest +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: smoketest +subjects: +- kind: ServiceAccount + name: smoketest + namespace: galoy-dev-smoketest +""" +k8s_yaml(blob(smoketest_rolebinding_yaml)) + +smoketest_pv_yaml=""" +apiVersion: v1 +kind: PersistentVolume +metadata: + name: smoketest-tasks +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + hostPath: + path: "/charts" +""" +k8s_yaml(blob(smoketest_pv_yaml)) + +smoketest_pvc_yaml=""" +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: smoketest-tasks + namespace: galoy-dev-smoketest +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + volumeName: smoketest-tasks +""" +k8s_yaml(blob(smoketest_pvc_yaml)) + +smoketest_pod_yaml=""" +apiVersion: v1 +kind: Pod +metadata: + name: smoketest + namespace: galoy-dev-smoketest +spec: + containers: + - name: smoketest + image: us.gcr.io/galoy-org/galoy-deployments-pipeline + imagePullPolicy: IfNotPresent + command: + - sleep + - "604800" + volumeMounts: + - name: smoketest-tasks + mountPath: /charts + serviceAccountName: smoketest + volumes: + - name: smoketest-tasks + persistentVolumeClaim: + claimName: smoketest-tasks +""" +k8s_yaml(blob(smoketest_pod_yaml)) diff --git a/dev/smoketest/main.tf b/dev/smoketest/main.tf deleted file mode 100644 index 866a26d00a..0000000000 --- a/dev/smoketest/main.tf +++ /dev/null @@ -1,74 +0,0 @@ -variable "name_prefix" {} - -locals { - smoketest_namespace = "${var.name_prefix}-smoketest" -} - -resource "kubernetes_persistent_volume_claim" "smoketest_tasks" { - metadata { - name = "smoketest-tasks-pv-claim" - namespace = local.smoketest_namespace - } - spec { - storage_class_name = "manual" - access_modes = ["ReadWriteOnce"] - resources { - requests = { - storage = "1Gi" - } - } - volume_name = kubernetes_persistent_volume.smoketest_tasks.metadata.0.name - } -} - -resource "kubernetes_persistent_volume" "smoketest_tasks" { - metadata { - name = "smoketest-tasks-pv-volume" - } - spec { - storage_class_name = "manual" - access_modes = ["ReadWriteOnce"] - capacity = { - storage = "1Gi" - } - persistent_volume_source { - host_path { - path = "/charts" - } - } - } -} - -resource "kubernetes_pod" "smoketest" { - metadata { - name = "smoketest" - namespace = local.smoketest_namespace - } - - spec { - container { - image = "us.gcr.io/galoy-org/galoy-deployments-pipeline" - image_pull_policy = "IfNotPresent" - name = "smoketest" - - command = [ - "sleep", - "604800" - ] - - volume_mount { - mount_path = "/charts" - name = "smoketest-tasks-pv-storage" - } - } - - volume { - name = "smoketest-tasks-pv-storage" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.smoketest_tasks.metadata.0.name - } - } - - service_account_name = "smoketest" - } -} diff --git a/dev/stablesats/Tiltfile b/dev/stablesats/Tiltfile new file mode 100644 index 0000000000..2de4258f70 --- /dev/null +++ b/dev/stablesats/Tiltfile @@ -0,0 +1,46 @@ +load('ext://namespace', 'namespace_create') +load('ext://secret', 'secret_from_dict') +load('ext://helm_resource', 'helm_resource') +load('../common/Tiltfile', 'copy_secret', 'helm_release') + +name_prefix = 'galoy-dev' +stablesats_namespace = '{}-stablesats'.format(name_prefix) +smoketest_namespace = '{}-smoketest'.format(name_prefix) + +namespace_create(stablesats_namespace) + +k8s_yaml(secret_from_dict( + name='stablesats', + namespace=stablesats_namespace, + inputs={ + 'pg-user-pw': 'stablesats', + 'pg-con': 'postgres://stablesats:stablesats@stablesats-postgresql:5432/stablesats', + 'okex-secret-key': 'key', + 'okex-passphrase': 'passphrase', + 'galoy-phone-code': '123456', + 'bria-profile-api-key': 'key' + } +)) + +# stablesats smoketest secret +k8s_yaml(secret_from_dict( + name='stablesats-smoketest', + namespace=smoketest_namespace, + inputs={ + 'price_server_grpc_host': 'stablesats-price.{}.svc.cluster.local'.format(stablesats_namespace), + 'price_server_grpc_port': 3325 + } +)) + +helm_release( + '../../charts/stablesats', + name='stablesats', + namespace=stablesats_namespace, + values=['./stablesats-values.yml'], + dependency_build=True +) + + +k8s_resource(workload='stablesats-price', labels='stablesats') +# TODO: Fix stablesats dealer, involves provisioning phone and code and injecting into both galoy and stablesats +k8s_resource(workload='stablesats-dealer', pod_readiness='ignore', labels='stablesats') diff --git a/dev/stablesats/main.tf b/dev/stablesats/main.tf deleted file mode 100644 index 2f6eec195e..0000000000 --- a/dev/stablesats/main.tf +++ /dev/null @@ -1,54 +0,0 @@ -variable "name_prefix" { - default = "galoy-dev" -} - -variable "okex_secret_key" {} -variable "okex_passphrase" {} -variable "galoy_phone_code" {} -variable "galoy_phone_number" {} -variable "okex_api_key" {} - -locals { - stablesats_namespace = "${var.name_prefix}-stablesats" -} - -resource "kubernetes_namespace" "stablesats" { - metadata { - name = local.stablesats_namespace - } -} - -resource "random_password" "postgresql" { - length = 20 - special = false -} - -resource "kubernetes_secret" "stablesats_secrets" { - metadata { - name = "stablesats" - namespace = kubernetes_namespace.stablesats.metadata[0].name - } - - data = { - pg-user-pw : random_password.postgresql.result - pg-con : "postgres://stablesats:${random_password.postgresql.result}@stablesats-postgresql:5432/stablesats" - okex-secret-key : var.okex_secret_key - okex-passphrase : var.okex_passphrase - galoy-phone-code : var.galoy_phone_code - } -} - -resource "helm_release" "stablesats" { - name = "stablesats" - chart = "${path.module}/../../charts/stablesats" - namespace = kubernetes_namespace.stablesats.metadata[0].name - - values = [ - templatefile("${path.module}/stablesats-values.yml.tmpl", { - galoy_phone_number : var.galoy_phone_number, - okex_api_key : var.okex_api_key - }) - ] - - dependency_update = true -} diff --git a/dev/stablesats/stablesats-values.yml.tmpl b/dev/stablesats/stablesats-values.yml similarity index 76% rename from dev/stablesats/stablesats-values.yml.tmpl rename to dev/stablesats/stablesats-values.yml index b96f6ee819..8fd811b9f1 100644 --- a/dev/stablesats/stablesats-values.yml.tmpl +++ b/dev/stablesats/stablesats-values.yml @@ -2,11 +2,11 @@ secrets: create: false stablesats: galoy: - phoneNumber: '"${galoy_phone_number}"' + phoneNumber: '+16505554350' exchanges: okex: client: - apiKey: "${okex_api_key}" + apiKey: "dummy" simulated: true crash_report_config_danger: true diff --git a/flake.nix b/flake.nix index 4a13059548..e5f20afd0c 100644 --- a/flake.nix +++ b/flake.nix @@ -24,12 +24,15 @@ nativeBuildInputs = [ alejandra kubectl + python3 tilt + jq k3d vendir ytt yq-go kubernetes-helm + terraform ]; shellHook = '' diff --git a/images/chain-dl/Dockerfile b/images/chain-dl/Dockerfile index 4d1c4b01f8..6d85df182b 100644 --- a/images/chain-dl/Dockerfile +++ b/images/chain-dl/Dockerfile @@ -1,4 +1,4 @@ -FROM lncm/bitcoind:v24.0.1 +FROM lncm/bitcoind:v25.1 USER root @@ -7,7 +7,7 @@ RUN apk add curl python3 USER bitcoind RUN cd ~ && \ - curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-359.0.0-linux-x86_64.tar.gz \ + curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-455.0.0-linux-x86_64.tar.gz \ && tar -xvzf ./google-cloud* \ && ./google-cloud-sdk/install.sh --quiet \ && rm *.tar.gz diff --git a/images/lnd-sidecar/Dockerfile b/images/lnd-sidecar/Dockerfile index 19f0e7f658..c53e54cfa9 100644 --- a/images/lnd-sidecar/Dockerfile +++ b/images/lnd-sidecar/Dockerfile @@ -1,4 +1,4 @@ -FROM lightninglabs/lnd:v0.16.2-beta as lnd +FROM lightninglabs/lnd:v0.17.3-beta as lnd FROM lightninglabs/loop:v0.20.1-beta as loop FROM alpine/k8s:1.23.14 diff --git a/images/mongo-backup/Dockerfile b/images/mongo-backup/Dockerfile index 9be31d6418..86e468919c 100644 --- a/images/mongo-backup/Dockerfile +++ b/images/mongo-backup/Dockerfile @@ -1,5 +1,5 @@ FROM gcr.io/google.com/cloudsdktool/cloud-sdk:alpine -RUN apk add --update --no-cache mongodb-tools=4.2.14-r6 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community +RUN apk add --update --no-cache mongodb-tools=100.8.0-r2 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community aws-cli ENTRYPOINT []