diff --git a/.eslintignore b/.eslintignore
index b6bd735f63..c4daefea0e 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,6 +1,6 @@
.next
public
-generated
+**/generated
dist
build
postman-scripts
\ No newline at end of file
diff --git a/.github/workflows/lint_test_build.yml b/.github/workflows/lint_test_build.yml
index c3dec2b099..a0b4770427 100644
--- a/.github/workflows/lint_test_build.yml
+++ b/.github/workflows/lint_test_build.yml
@@ -58,7 +58,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: ./.github/workflows/rafiki/env-setup
- - run: pnpm --filter frontend test
+ - run: pnpm --filter frontend build
auth:
runs-on: ubuntu-22.04
diff --git a/.gitignore b/.gitignore
index 2f866f81b5..08567fbc25 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,9 @@ dist
**/.terraform
tmp
+
+# Remix
+.cache
+build
+**/public/build
+**/styles/*.css
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
index 1a449b1503..39e1943540 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -10,3 +10,5 @@ Dockerfile
.gitignore
.prettierignore
infrastructure/helm/**
+build
+**/styles/*.css
\ No newline at end of file
diff --git a/localenv/README.md b/localenv/README.md
index afb6632dae..b63cc2f09a 100644
--- a/localenv/README.md
+++ b/localenv/README.md
@@ -34,11 +34,11 @@ pnpm localenv:psql:dbvolumes:remove
```
The local environment consists of a primary Rafiki instance and a secondary Rafiki instance, each with
-its own docker compose files ([Cloud Nine Wallet](./docker-compose.cnw.yml), [Happy Life Bank](./docker-compose.hlf.yml)).
-The primary Cloud Nine Wallet docker compose file (`docker-compose.cnw.yml`) includes the main Rafiki services `backend` and `auth`, as well
+its own docker compose files ([Cloud Nine Wallet](./cloud-nine-wallet/docker-compose.yml), [Happy Life Bank](./happy-life-bank/docker-compose.yml)).
+The primary Cloud Nine Wallet docker compose file (`./cloud-nine-wallet/docker-compose.yml`) includes the main Rafiki services `backend` and `auth`, as well
as the required data stores tigerbeetle (if enabled), redis, and postgres, so it can be run on its own. Furthermore,
both include the `local-signature-utils` signature generation app for Postman.
-The secondary Happy Life Bank docker compose file (`docker-compose.hlb.yml`) includes only the Rafiki services, not the data stores. It uses the
+The secondary Happy Life Bank docker compose file (`./happy-life-bank/docker-compose.yml`) includes only the Rafiki services, not the data stores. It uses the
data stores created by the primary Rafiki instance so it can't be run by itself.
The `pnpm localenv:start` command starts both the primary instance and the secondary.
@@ -54,20 +54,26 @@ The `pnpm localenv:start` command starts both the primary instance and the secon
(c) Open Payments API - accessible at http://localhost:3000
-(d) Open Payments Auth API - accessible at accessible at http://localhost:3006
+(d) Rafiki Admin - accessible at http://localhost:3010
-(e) Postman Signature Service - accessible at accessible at http://localhost:3040
+(e) Open Payments Auth API - accessible at http://localhost:3006
+
+(f) Postman Signature Service - accessible at http://localhost:3040
#### Happy Life Bank
-(f) User Interface - accessible at http://localhost:3031
+(g) User Interface - accessible at http://localhost:3031
+
+(h) Admin API - accessible at http://localhost:4001/graphql
+
+(i) Open Payments API - accessible at http://localhost:4000
-(g) Admin API - accessible at http://localhost:4001/graphql
+(j) Rafiki Admin - accessible at http://localhost:4010
-(h) Open Payments API - accessible at http://localhost:4000
+(k) Open Payments Auth API - accessible at http://localhost:4006
-(i) Open Payments Auth API - accessible at accessible at http://localhost:4006
+(l) Postman Signature Service - accessible at http://localhost:3041
-(j) Postman Signature Service - accessible at accessible at http://localhost:3041
+#### Database
-(k) Postgres Server - accessible at http://localhost:5432
+(m) Postgres Server - accessible at http://localhost:5432
diff --git a/localenv/cloud-nine-wallet/docker-compose.yml b/localenv/cloud-nine-wallet/docker-compose.yml
index 9a1930e5e3..78d3f14c56 100644
--- a/localenv/cloud-nine-wallet/docker-compose.yml
+++ b/localenv/cloud-nine-wallet/docker-compose.yml
@@ -109,6 +109,21 @@ services:
restart: unless-stopped
networks:
- rafiki
+ admin:
+ hostname: cloud-nine-wallet-admin
+ build:
+ context: ../..
+ dockerfile: ./packages/frontend/Dockerfile
+ restart: always
+ networks:
+ - rafiki
+ ports:
+ - '3010:3010'
+ environment:
+ PORT: 3010
+ GRAPHQL_URL: http://cloud-nine-wallet-backend:3001/graphql
+ depends_on:
+ - backend
volumes:
database-data: # named volumes can be managed easier using docker-compose
diff --git a/localenv/happy-life-bank/docker-compose.yml b/localenv/happy-life-bank/docker-compose.yml
index 4504fdb694..44533e85d2 100644
--- a/localenv/happy-life-bank/docker-compose.yml
+++ b/localenv/happy-life-bank/docker-compose.yml
@@ -85,6 +85,21 @@ services:
KEY_FILE: /workspace/private-key.pem
volumes:
- ./private-key.pem:/workspace/private-key.pem
+ admin:
+ hostname: happy-life-bank-admin
+ build:
+ context: ../..
+ dockerfile: ./packages/frontend/Dockerfile
+ restart: always
+ networks:
+ - rafiki
+ ports:
+ - '4010:4010'
+ environment:
+ PORT: 4010
+ GRAPHQL_URL: http://happy-life-bank-backend:3001/graphql
+ depends_on:
+ - backend
networks:
rafiki:
diff --git a/localenv/local-dev.drawio b/localenv/local-dev.drawio
index a4464fe102..601cc2a7ae 100644
--- a/localenv/local-dev.drawio
+++ b/localenv/local-dev.drawio
@@ -1 +1,212 @@
-7Zxbc9o4FIB/DTPdBxj5Cn4MSZPutJ3NbjbbpG8CC+PGWNSIAP31K+GrbAEmYMlJ2plMrYN8O5/ORUe2O8blbH0Twfn0K3ZR0NGBF/lux7jq6LpG/6hgDj3ECViPO/9XKgSJdOm7aMF1JBgHxJ/zwjEOQzQmnAxGEV7x3SY4qF7G3RgGqCL95rtkGksHFsjln5DvTdMTaSD5ZQbTzolgMYUuXhVExseOcRlhTOKt2foSBUwzqV7i/a53/JpdWIRCUmeHCZmh6+6XiXYD4fDv+5/X3a/funo/uTiySe8YuVQBSTPEIf1vGOFl6CJ2HEBbOCJT7OEQBl8wnlOhRoU/ECGbhBZcEkxFUzILkl/R2icPbPeelbQek4Ox7at1sbEpNG5R5M8QQVEqC90LxpA28TMMYsm1H6TniW+G3cFOJSWiBV5G46TXzff7z0Nj/Wn5/fPzED/896gPta6WIaIDF2F6FdGG7hehABL/mT8+TMaUl/XLdr3FPj2zDtZxD9PQekbhn27HR9jEPxs24I9IYOQhkhwkh0s3CleVi7bIj8BvWHLwvwFsHCfTaozT7rvSAdXdMrmFW7wgXkQdYZnfgkT4KfNVOg+C+qA56zdbe8wX9yYBXo2nMCI9FxI4gguGezX1Cbqbw62eV7RfRugZRQSt9zOq6j7ZwXB2jPVV7lf7iWhacKl9sJsWp+djlapXlPqv76FohBChyny1etXMql4HMvVqVPT6D3L9VzxSdYFGmxqpQjed5j6Nu2l6sQ9ZqKWNxzxms2YeqLetTbG1J1Qn15f7fHBen2/G/WIf3GBsOImhYb+1UGs2Emo1hw+1hiE31JoV7zUO8NLthn6IuisYBIh0qdqnFZo8OpFrKmA6g5eicw1eUaDqpbLZSNFNlXPMsw1xWcnk6/RSVk0vpav0UpKcVDIdTLcLAHdPB984dkMl9oFcy+2CHtB4jNrAaQKkeKT19w81BfSVpiaaIdXq+SKQVtPqewY3YA4OlmxcjAO4WPjjSiYkHE8K0J+aRp2GXpLlp+g5M9QPeXxpqazVTCrb5zM0PS23SaruaY5CuAd87NuDazcGd5972TtPGcHxE1Wr8qlKeU6XrYkom6po1eKfpBTocFzKwqTu9IuBsgeYjo9cMTmjHdk1A9qp9nYaWOlllsMcHWDxHIGjnOPZ/aEBdpQjJAU7XdYcRlrcaoZT2Rdr5ap1w3HLPhy3lMercmlNtKQiOV5pFaU0OkMvzc7bXmQZ1AxNalcAJD1rIc9DDRrxULatdgVgUPFQUzifb7qBP0E0pQ6f2lH/t8y21f/N3z5qz7ByavoopfV/WS5KIkJxeUJaBbgudqX1f0mFoh3YNYnc5ZX+64JXW/qXtGb7otJ/vRJ+fNw+OHJ9oNnif134p2ZQJ8HXJT1WJFyDa0/x32kmix2oLf7rkmaML1lgfXtwJRf/nYNTlLaU/q3SZK4Fpf/qE16Ssp8jSsZ9rmQMeo5j77eoZkvG6QOoB+PZqeZ2GlnJsxfQA9lDKy9OOo4aFqC8IhRnPa0fFs0Uiqz0LYzEt9jlQlF8A82FWLnr68c9LSfvjRvQCNxyFVD2OkU6tnfHWPWxtVQBlLpMIVZaXxBb7YCeduj6z3TTY5sfRn/QPhfuzA/TX+nZCh0qmqU6Irz64pdHLnGAo9zUJnSAl0Qw8L2QNqP47odM4f4YBheJfOa7LjuLEBcP9AzENHA4G7IFwMqO7XzAqsVuEbAxA/bXHFFe4BZuZvR2F+8MXcnWdEtga3pD6MTLSa95wVucvzUSSMoL3qYm98GE6rub1Qe1FnREQ7IUvc+peu3bGKiesBnvLc0SJ5tSsizZxqEfSrLaZBqVFVflpqFX9ceFb5DGUCr9uWRfmhgGaELyVhbhPfkp2fZKVId1u8ajqU1lZGKk1denRRnZVGVG1k5yyjMyvfps24cnxin/WAO4QxG96xpMUl2PqTpY7Wa3tumB/V9wtD0U0+2cOevtvVnDjnXFjkWD3SKOe8fgPgMkU+NfpTcFH30QQtIbyyaq+ZjIviDjdr9gqMCfjMCEjWZ2VXHfUZTb17uaB5XLMpal2OqMAzEwAToRA1VGsx0+tN82mma17Cai6QrDH7jYPpj3zi20nKVqAqamVKb1XC5KQ+UMMqx3hcT/N1GOqKOcaD2f67fSSlvpeYVWakhlWm/i8aOFVtpOoiIrPRNR2sw/HBnXYvJvaxof/wc=
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/localenv/local-dev.png b/localenv/local-dev.png
index a434c46a43..8073a383e0 100644
Binary files a/localenv/local-dev.png and b/localenv/local-dev.png differ
diff --git a/packages/backend/.graphqlconfig b/packages/backend/.graphqlconfig
index ae0b7e4d1c..e9b42aaf34 100644
--- a/packages/backend/.graphqlconfig
+++ b/packages/backend/.graphqlconfig
@@ -1,4 +1,5 @@
{
"name": "Rafiki GraphQL Schema",
- "schemaPath": "/src/graphql/schema.graphql"
+ "schemaPath": "/src/graphql/schema.graphql",
+ "documents": "../frontend/app/**/*.{graphql,js,ts,jsx,tsx}"
}
diff --git a/packages/backend/codegen.yml b/packages/backend/codegen.yml
index 252bf26361..e966fa0ada 100644
--- a/packages/backend/codegen.yml
+++ b/packages/backend/codegen.yml
@@ -1,5 +1,6 @@
overwrite: true
schema: './src/graphql/schema.graphql'
+documents: '../frontend/app/**/!(*.d).{ts,tsx}'
generates:
src/graphql/generated/graphql.ts:
plugins:
@@ -26,3 +27,17 @@ generates:
src/graphql/generated/graphql.schema.json:
plugins:
- 'introspection'
+ ../frontend/app/generated/graphql.ts:
+ plugins:
+ - 'typescript'
+ - 'typescript-resolvers'
+ - 'typescript-operations'
+ config:
+ omitOperationSuffix: true
+ defaultMapper: Partial<{T}>
+ # By default it is T | null. But the service code uses typescript's optional types (`foo?: T`) which are `T | undefined`. This saves the trouble of converting them explicitly.
+ inputMaybeValue: T | undefined
+ scalars:
+ UInt8: number
+ UInt64: bigint
+
diff --git a/packages/backend/package.json b/packages/backend/package.json
index 5b480112e9..13f309808f 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -15,6 +15,7 @@
"@graphql-codegen/cli": "3.2.2",
"@graphql-codegen/introspection": "3.0.1",
"@graphql-codegen/typescript": "3.0.2",
+ "@graphql-codegen/typescript-operations": "^3.0.0",
"@graphql-codegen/typescript-resolvers": "3.1.1",
"@types/jest": "^29.5.0",
"@types/koa": "2.13.6",
diff --git a/packages/frontend/.eslintignore b/packages/frontend/.eslintignore
new file mode 100644
index 0000000000..dc9b2375c7
--- /dev/null
+++ b/packages/frontend/.eslintignore
@@ -0,0 +1 @@
+generated
\ No newline at end of file
diff --git a/packages/frontend/.eslintrc.yml b/packages/frontend/.eslintrc.yml
new file mode 100644
index 0000000000..75a658df31
--- /dev/null
+++ b/packages/frontend/.eslintrc.yml
@@ -0,0 +1,15 @@
+extends:
+ - '../../.eslintrc.yml'
+ - '@remix-run/eslint-config/node'
+ - 'plugin:react/recommended'
+ - 'plugin:jsx-a11y/recommended'
+rules:
+ 'react/jsx-uses-react': 'off'
+ 'react/react-in-jsx-scope': 'off'
+ '@typescript-eslint/quotes': ['warn', 'single', { avoidEscape: true, allowTemplateLiterals: true }]
+ '@typescript-eslint/consistent-type-imports': 'warn'
+ 'jsx-a11y/anchor-has-content': 'warn'
+ 'jsx-a11y/anchor-is-valid': 'warn'
+settings:
+ react:
+ version: "detect"
diff --git a/packages/frontend/.gitignore b/packages/frontend/.gitignore
deleted file mode 100644
index 0b0cdd8a80..0000000000
--- a/packages/frontend/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-build
-
-/dist
-.env
-src/coverage
diff --git a/packages/frontend/Dockerfile b/packages/frontend/Dockerfile
new file mode 100644
index 0000000000..6ca40c6096
--- /dev/null
+++ b/packages/frontend/Dockerfile
@@ -0,0 +1,21 @@
+FROM node:18.13.0-slim as builder
+
+WORKDIR /workspace
+
+RUN apt update
+RUN apt install -y curl xz-utils python3 build-essential
+
+# version in curl is not the version used. Dependent on the last command
+RUN corepack enable
+RUN corepack prepare pnpm@7.25.1 --activate
+
+# pnpm fetch does require only lockfile
+COPY pnpm-lock.yaml ./
+RUN pnpm fetch
+
+ADD . ./
+RUN pnpm install -r --offline
+
+RUN pnpm --filter frontend build
+
+CMD pnpm --filter frontend start
diff --git a/packages/frontend/README.md b/packages/frontend/README.md
index d11d3bd66e..d2233437d6 100644
--- a/packages/frontend/README.md
+++ b/packages/frontend/README.md
@@ -1 +1,50 @@
-# RAIO frontend
+# Rafiki Admin
+
+## Development
+
+This project assumes that you have a local Rafiki backend instance up and running. See the `Environment Setup` and `Local Development` sections in the main [README](../../README.md) and the `Local Playground` section in the infrastructure/local [README](../../infrastructure/local/README.md).
+
+To start the project in development mode, we first need to generate the GraphQL types for our queries and mutations.
+
+To generate the GraphQL types file run:
+
+```sh
+pnpm --filter backend generate
+```
+
+To start the application run:
+
+```sh
+pnpm --filter frontend dev
+```
+
+Now you can access the application on [http://localhost:3005](http://localhost:3005).
+
+> NOTE: When running Rafiki Admin in the development environment, it will connect to Cloud Nine Wallet Admin GraphQL - [http://localhost:3001/graphql](http://localhost:3001/graphql).
+
+## Structure
+
+```
+📦frontend
+ ┣ 📂app
+ ┃ ┣ 📂components
+ ┃ ┃ ┣ 📂ui
+ ┃ ┣ 📂generated
+ ┃ ┣ 📂lib
+ ┃ ┃ ┣ 📂api
+ ┃ ┣ 📂routes
+ ┃ ┣ 📂shared
+ ┃ ┣ 📂styles
+ ┣ 📂public
+```
+
+- `app`: source of the application
+ - `components`: domain-related components
+ - `ui`: reusable code blocks and components that comprise the UI/design system
+ - `generated`: types generated by GraphQL Code Gen
+ - `lib`: business logic
+ - `api`: GraphQL queries and mutations
+ - `routes`: outer layer of the application
+ - `shared`: utilility functions or types
+ - `styles`: check out the styles [README](./app/styles/README.md)
+- `public`: static files and assets that are served to the browser
diff --git a/packages/frontend/app/components/DangerZone.tsx b/packages/frontend/app/components/DangerZone.tsx
new file mode 100644
index 0000000000..31d301528a
--- /dev/null
+++ b/packages/frontend/app/components/DangerZone.tsx
@@ -0,0 +1,20 @@
+import { type ReactNode } from 'react'
+
+type DangerZoneProps = {
+ title: string
+ children: ReactNode
+}
+
+export const DangerZone = ({ title, children }: DangerZoneProps) => {
+ return (
+
+
+
{title}
+
+ Please note that this action is not reversible. Continue with caution.
+
+
+ {children}
+
+ )
+}
diff --git a/packages/frontend/app/components/PageHeader.tsx b/packages/frontend/app/components/PageHeader.tsx
new file mode 100644
index 0000000000..a946dc4279
--- /dev/null
+++ b/packages/frontend/app/components/PageHeader.tsx
@@ -0,0 +1,20 @@
+import { cx } from 'class-variance-authority'
+import type { ReactNode } from 'react'
+
+type PageHeaderProps = {
+ children: ReactNode
+ className?: string
+}
+
+export const PageHeader = ({ children, className }: PageHeaderProps) => {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/packages/frontend/app/components/Sidebar.tsx b/packages/frontend/app/components/Sidebar.tsx
new file mode 100644
index 0000000000..d6ff2cd2c7
--- /dev/null
+++ b/packages/frontend/app/components/Sidebar.tsx
@@ -0,0 +1,135 @@
+import { Dialog, Transition } from '@headlessui/react'
+import { NavLink } from '@remix-run/react'
+import { cx } from 'class-variance-authority'
+import { Fragment, useState } from 'react'
+import { Bars, X } from './icons'
+
+const navigation = [
+ {
+ name: 'Home',
+ href: '/'
+ },
+ {
+ name: 'Peers',
+ href: '/peers'
+ },
+ {
+ name: 'Assets',
+ href: '/assets'
+ }
+]
+
+export const Sidebar = () => {
+ const [sidebarIsOpen, setSidebarIsOpen] = useState(false)
+
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
diff --git a/packages/frontend/app/components/Snackbar.tsx b/packages/frontend/app/components/Snackbar.tsx
new file mode 100644
index 0000000000..291127185b
--- /dev/null
+++ b/packages/frontend/app/components/Snackbar.tsx
@@ -0,0 +1,76 @@
+import { Transition } from '@headlessui/react'
+import { cx } from 'class-variance-authority'
+import type { FC } from 'react'
+import { Fragment, useEffect } from 'react'
+import { type Message } from '~/lib/message.server'
+import { CheckCircleSolid, XCircleSolid } from './icons'
+
+interface SnackbarProps {
+ id: string
+ show?: boolean
+ // The label value.
+ message: Message | null
+ action?: string
+ icon?: string
+ onClose(): void
+ // Offset to the right for the WalletLayout on desktop
+ offset?: boolean
+ // ms delay after which the snackbar should be aut dismissed.
+ dismissAfter?: number
+}
+
+export const Snackbar: FC = ({
+ id,
+ message,
+ onClose,
+ offset,
+ show = false,
+ dismissAfter
+}) => {
+ useEffect(() => {
+ let timer: NodeJS.Timeout
+ if (dismissAfter && show) {
+ timer = setTimeout(() => {
+ onClose()
+ }, dismissAfter)
+ }
+ return () => clearTimeout(timer)
+ }, [dismissAfter, onClose, show])
+
+ if (!message) return null
+
+ return (
+
+
+
+
+ {message.type === 'success' && (
+
+ )}
+ {message.type === 'error' && (
+
+ )}
+
{message.content}
+
+
+
+
+ )
+}
diff --git a/packages/frontend/app/components/icons.tsx b/packages/frontend/app/components/icons.tsx
new file mode 100644
index 0000000000..ca946591d9
--- /dev/null
+++ b/packages/frontend/app/components/icons.tsx
@@ -0,0 +1,180 @@
+import { cx } from 'class-variance-authority'
+import type { SVGProps } from 'react'
+
+export const Bars = (props: SVGProps) => {
+ return (
+
+ )
+}
+
+export const CheckCircleSolid = (props: SVGProps) => {
+ return (
+
+ )
+}
+
+const DIRECTION = {
+ up: 'rotate-180',
+ down: 'rotate-0',
+ left: 'rotate-90',
+ right: '-rotate-90'
+} as const
+
+type Direction = keyof typeof DIRECTION
+
+type ChevronProps = SVGProps & {
+ direction?: Direction
+}
+
+export const Chevron = ({
+ direction = 'down',
+ className,
+ ...props
+}: ChevronProps) => {
+ return (
+
+ )
+}
+
+export const Eye = (props: SVGProps) => {
+ return (
+
+ )
+}
+
+export const EyeSlash = (props: SVGProps) => {
+ return (
+
+ )
+}
+
+export const Info = (props: SVGProps) => {
+ return (
+
+ )
+}
+
+export const X = (props: SVGProps) => {
+ return (
+
+ )
+}
+
+export const XCircle = (props: SVGProps) => {
+ return (
+
+ )
+}
+
+export const XCircleSolid = (props: SVGProps) => {
+ return (
+
+ )
+}
diff --git a/packages/frontend/app/components/index.ts b/packages/frontend/app/components/index.ts
new file mode 100644
index 0000000000..50d4c57b16
--- /dev/null
+++ b/packages/frontend/app/components/index.ts
@@ -0,0 +1,4 @@
+export * from './DangerZone'
+export * from './PageHeader'
+export * from './Sidebar'
+export * from './Snackbar'
diff --git a/packages/frontend/app/components/ui/Button.tsx b/packages/frontend/app/components/ui/Button.tsx
new file mode 100644
index 0000000000..3f8e661af5
--- /dev/null
+++ b/packages/frontend/app/components/ui/Button.tsx
@@ -0,0 +1,41 @@
+import { cva, type VariantProps } from 'class-variance-authority'
+import { forwardRef } from 'react'
+import { ButtonOrLink, type ButtonOrLinkProps } from './ButtonOrLink'
+
+const buttonStyles = cva(
+ 'inline-flex items-center justify-center focus:outline-none disabled:cursor-not-allowed',
+ {
+ variants: {
+ intent: {
+ default:
+ 'bg-[#F37F64] hover:bg-[#DA725A] disabled:bg-mercury disabled:text-gray-500 shadow-md text-white',
+ danger: 'bg-red-500 hover:bg-red-600 shadow-md text-white'
+ },
+ size: {
+ sm: 'px-2 py-1 rounded-md font-medium',
+ md: 'px-3 py-2 rounded-md font-medium'
+ }
+ },
+ defaultVariants: {
+ intent: 'default',
+ size: 'md'
+ }
+ }
+)
+
+type ButtonProps = VariantProps &
+ ButtonOrLinkProps & {
+ ['aria-label']: string
+ }
+
+export const Button = forwardRef(
+ ({ intent, children, ...props }, ref) => {
+ return (
+
+ {children}
+
+ )
+ }
+)
+
+Button.displayName = 'Button'
diff --git a/packages/frontend/app/components/ui/ButtonOrLink.tsx b/packages/frontend/app/components/ui/ButtonOrLink.tsx
new file mode 100644
index 0000000000..298346ba48
--- /dev/null
+++ b/packages/frontend/app/components/ui/ButtonOrLink.tsx
@@ -0,0 +1,63 @@
+import { Link, type LinkProps } from '@remix-run/react'
+import { forwardRef, type ComponentProps } from 'react'
+
+type AnchorOrLinkProps = ComponentProps<'a'> & Partial
+
+const AnchorOrLink = forwardRef(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ({ children, href, prefetch, to, ...props }, ref: any) => {
+ const isAnchor = typeof href !== 'undefined'
+
+ if (isAnchor) {
+ if (prefetch) {
+ console.warn(
+ 'Property "prefetch" does not have any effect when using it with simple anchor tag.'
+ )
+ }
+
+ return (
+
+ {children}
+
+ )
+ }
+
+ return (
+
+ {children}
+
+ )
+ }
+)
+AnchorOrLink.displayName = 'AnchorOrLink'
+
+export type ButtonOrLinkProps = Omit<
+ ComponentProps<'button'> & AnchorOrLinkProps,
+ 'ref'
+> &
+ (
+ | { to: LinkProps['to']; href?: never }
+ | { to?: never; href: string }
+ | { to?: never; href?: never }
+ )
+
+export const ButtonOrLink = forwardRef<
+ HTMLButtonElement | HTMLAnchorElement,
+ ButtonOrLinkProps
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+>(({ to, href, ...props }, ref: any) => {
+ const isLink = typeof to !== 'undefined' || typeof href !== 'undefined'
+
+ if (isLink) {
+ return
+ }
+
+ return
+})
+ButtonOrLink.displayName = 'ButtonOrLink'
diff --git a/packages/frontend/app/components/ui/ErrorPanel.tsx b/packages/frontend/app/components/ui/ErrorPanel.tsx
new file mode 100644
index 0000000000..1de0da4870
--- /dev/null
+++ b/packages/frontend/app/components/ui/ErrorPanel.tsx
@@ -0,0 +1,35 @@
+import { XCircle } from '../icons'
+
+type ErrorPanelProps = {
+ errors?: string[]
+}
+
+export const ErrorPanel = ({ errors }: ErrorPanelProps) => {
+ if (!errors) return null
+ if (errors.length === 0) return null
+
+ let errorMessage = 'There was an error with your submission!'
+ if (errors?.length && errors.length > 1) {
+ errorMessage = `There were ${errors?.length} errors with your submission`
+ }
+
+ return (
+
+
+
+
+
+
+
{errorMessage}
+
+
+ {errors?.map((error) => (
+ - {error}
+ ))}
+
+
+
+
+
+ )
+}
diff --git a/packages/frontend/app/components/ui/FieldError.tsx b/packages/frontend/app/components/ui/FieldError.tsx
new file mode 100644
index 0000000000..fe0d3d9998
--- /dev/null
+++ b/packages/frontend/app/components/ui/FieldError.tsx
@@ -0,0 +1,21 @@
+export interface FieldErrorProps {
+ error?: string | string[]
+}
+
+export const FieldError = ({ error }: FieldErrorProps) => {
+ if (!error) return null
+
+ return (
+
+ {Array.isArray(error) ? (
+ <>
+ {error.map((e) => (
+
{e}
+ ))}
+ >
+ ) : (
+ error
+ )}
+
+ )
+}
diff --git a/packages/frontend/app/components/ui/Input.tsx b/packages/frontend/app/components/ui/Input.tsx
new file mode 100644
index 0000000000..e3755f9aec
--- /dev/null
+++ b/packages/frontend/app/components/ui/Input.tsx
@@ -0,0 +1,38 @@
+import type { ComponentPropsWithoutRef } from 'react'
+import { forwardRef, useId } from 'react'
+
+import { FieldError } from './FieldError'
+import { Label } from './Label'
+
+type InputProps = Omit, 'className'> & {
+ label?: string
+ error?: string | string[]
+}
+
+export const Input = forwardRef(
+ ({ label, type, error, ...props }, ref) => {
+ const id = useId()
+
+ return (
+
+ {label && (
+
+ )}
+
+
+
+
+
+ )
+ }
+)
+
+Input.displayName = 'Input'
diff --git a/packages/frontend/app/components/ui/Label.tsx b/packages/frontend/app/components/ui/Label.tsx
new file mode 100644
index 0000000000..d34c3b206c
--- /dev/null
+++ b/packages/frontend/app/components/ui/Label.tsx
@@ -0,0 +1,20 @@
+import type { ComponentPropsWithoutRef, ReactNode } from 'react'
+
+type LabelProps = Omit, 'children'> & {
+ children: ReactNode
+ required?: boolean
+}
+
+export const Label = ({
+ htmlFor,
+ children,
+ required,
+ ...props
+}: LabelProps) => {
+ return (
+
+ )
+}
diff --git a/packages/frontend/app/components/ui/PasswordInput.tsx b/packages/frontend/app/components/ui/PasswordInput.tsx
new file mode 100644
index 0000000000..564b63011d
--- /dev/null
+++ b/packages/frontend/app/components/ui/PasswordInput.tsx
@@ -0,0 +1,54 @@
+import type { ComponentPropsWithoutRef } from 'react'
+import { forwardRef, useId, useState } from 'react'
+import { Eye, EyeSlash } from '../icons'
+import { FieldError } from './FieldError'
+import { Label } from './Label'
+
+type InputProps = Omit<
+ ComponentPropsWithoutRef<'input'>,
+ 'className' | 'type'
+> & {
+ label?: string
+ error?: string | string[]
+}
+
+export const PasswordInput = forwardRef(
+ ({ label, error, ...props }, ref) => {
+ const id = useId()
+ const [isVisible, setIsVisible] = useState(false)
+
+ return (
+
+ {label && (
+
+ )}
+
+
+
+
+
+
+
+ )
+ }
+)
+
+PasswordInput.displayName = 'PasswordInput'
diff --git a/packages/frontend/app/components/ui/Select.tsx b/packages/frontend/app/components/ui/Select.tsx
new file mode 100644
index 0000000000..69c1d1acbb
--- /dev/null
+++ b/packages/frontend/app/components/ui/Select.tsx
@@ -0,0 +1,35 @@
+import { forwardRef, useId, type ComponentPropsWithoutRef } from 'react'
+import { FieldError } from './FieldError'
+import { Label } from './Label'
+
+type SelectProps = Omit, 'className'> & {
+ label?: string
+ error?: string | string[]
+}
+
+export const Select = forwardRef(
+ ({ label, error, children, ...props }, ref) => {
+ const id = useId()
+
+ return (
+
+ {label && (
+
+ )}
+
+
+
+ )
+ }
+)
+
+Select.displayName = 'Select'
diff --git a/packages/frontend/app/components/ui/Table.tsx b/packages/frontend/app/components/ui/Table.tsx
new file mode 100644
index 0000000000..3fd784279e
--- /dev/null
+++ b/packages/frontend/app/components/ui/Table.tsx
@@ -0,0 +1,97 @@
+import { cx } from 'class-variance-authority'
+import { type ComponentProps, type ReactNode } from 'react'
+
+type TableProps = ComponentProps<'table'> & {
+ children: ReactNode
+}
+
+type THeadProps = ComponentProps<'thead'> & {
+ columns: string[]
+ thProps?: ComponentProps<'th'>
+ trProps?: ComponentProps<'tr'>
+}
+
+type TBodyProps = ComponentProps<'tbody'> & {
+ children: ReactNode
+}
+
+type TRowProps = ComponentProps<'tr'> & {
+ children: ReactNode
+}
+
+type TCellProps = ComponentProps<'td'> & {
+ children: ReactNode
+}
+
+const THead = ({
+ columns,
+ thProps,
+ trProps,
+ className,
+ ...props
+}: THeadProps) => {
+ return (
+
+
+ {columns.map((col) => (
+
+ {col}
+ |
+ ))}
+
+
+ )
+}
+
+const TBody = ({ children, ...props }: TBodyProps) => {
+ return {children}
+}
+
+const TRow = ({ children, className, ...props }: TRowProps) => {
+ return (
+
+ {children}
+
+ )
+}
+
+const TCell = ({ children, className, ...props }: TCellProps) => {
+ return (
+
+ {children}
+ |
+ )
+}
+
+export const Table = ({ children, className, ...props }: TableProps) => {
+ return (
+
+ )
+}
+
+Table.Head = THead
+Table.Body = TBody
+Table.Row = TRow
+Table.Cell = TCell
diff --git a/packages/frontend/app/components/ui/index.tsx b/packages/frontend/app/components/ui/index.tsx
new file mode 100644
index 0000000000..73facab4b7
--- /dev/null
+++ b/packages/frontend/app/components/ui/index.tsx
@@ -0,0 +1,8 @@
+export * from './Button'
+export * from './ErrorPanel'
+export * from './FieldError'
+export * from './Input'
+export * from './Label'
+export * from './PasswordInput'
+export * from './Select'
+export * from './Table'
diff --git a/packages/frontend/app/entry.client.tsx b/packages/frontend/app/entry.client.tsx
new file mode 100644
index 0000000000..8fbc4bd08f
--- /dev/null
+++ b/packages/frontend/app/entry.client.tsx
@@ -0,0 +1,22 @@
+import { RemixBrowser } from '@remix-run/react'
+import { startTransition, StrictMode } from 'react'
+import { hydrateRoot } from 'react-dom/client'
+
+function hydrate() {
+ startTransition(() => {
+ hydrateRoot(
+ document,
+
+
+
+ )
+ })
+}
+
+if (window.requestIdleCallback) {
+ window.requestIdleCallback(hydrate)
+} else {
+ // Safari doesn't support requestIdleCallback
+ // https://caniuse.com/requestidlecallback
+ window.setTimeout(hydrate, 1)
+}
diff --git a/packages/frontend/app/entry.server.tsx b/packages/frontend/app/entry.server.tsx
new file mode 100644
index 0000000000..d092e384b3
--- /dev/null
+++ b/packages/frontend/app/entry.server.tsx
@@ -0,0 +1,111 @@
+import { PassThrough } from 'stream'
+import type { EntryContext } from '@remix-run/node'
+import { Response } from '@remix-run/node'
+import { RemixServer } from '@remix-run/react'
+import isbot from 'isbot'
+import { renderToPipeableStream } from 'react-dom/server'
+
+const ABORT_DELAY = 5000
+
+export default function handleRequest(
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext
+) {
+ return isbot(request.headers.get('user-agent'))
+ ? handleBotRequest(
+ request,
+ responseStatusCode,
+ responseHeaders,
+ remixContext
+ )
+ : handleBrowserRequest(
+ request,
+ responseStatusCode,
+ responseHeaders,
+ remixContext
+ )
+}
+
+function handleBotRequest(
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext
+) {
+ return new Promise((resolve, reject) => {
+ let didError = false
+
+ const { pipe, abort } = renderToPipeableStream(
+ ,
+ {
+ onAllReady() {
+ const body = new PassThrough()
+
+ responseHeaders.set('Content-Type', 'text/html')
+
+ resolve(
+ new Response(body, {
+ headers: responseHeaders,
+ status: didError ? 500 : responseStatusCode
+ })
+ )
+
+ pipe(body)
+ },
+ onShellError(error: unknown) {
+ reject(error)
+ },
+ onError(error: unknown) {
+ didError = true
+
+ console.error(error)
+ }
+ }
+ )
+
+ setTimeout(abort, ABORT_DELAY)
+ })
+}
+
+function handleBrowserRequest(
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext
+) {
+ return new Promise((resolve, reject) => {
+ let didError = false
+
+ const { pipe, abort } = renderToPipeableStream(
+ ,
+ {
+ onShellReady() {
+ const body = new PassThrough()
+
+ responseHeaders.set('Content-Type', 'text/html')
+
+ resolve(
+ new Response(body, {
+ headers: responseHeaders,
+ status: didError ? 500 : responseStatusCode
+ })
+ )
+
+ pipe(body)
+ },
+ onShellError(err: unknown) {
+ reject(err)
+ },
+ onError(error: unknown) {
+ didError = true
+
+ console.error(error)
+ }
+ }
+ )
+
+ setTimeout(abort, ABORT_DELAY)
+ })
+}
diff --git a/packages/frontend/app/generated/graphql.ts b/packages/frontend/app/generated/graphql.ts
new file mode 100644
index 0000000000..11d5e4be5d
--- /dev/null
+++ b/packages/frontend/app/generated/graphql.ts
@@ -0,0 +1,1637 @@
+import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql';
+export type Maybe = T | null;
+export type InputMaybe = T | undefined;
+export type Exact = { [K in keyof T]: T[K] };
+export type MakeOptional = Omit & { [SubKey in K]?: Maybe };
+export type MakeMaybe = Omit & { [SubKey in K]: Maybe };
+export type RequireFields = Omit & { [P in K]-?: NonNullable };
+/** All built-in and custom scalars, mapped to their actual values */
+export type Scalars = {
+ ID: string;
+ String: string;
+ Boolean: boolean;
+ Int: number;
+ Float: number;
+ UInt8: number;
+ UInt64: bigint;
+};
+
+export type AddAssetLiquidityInput = {
+ /** Amount of liquidity to add. */
+ amount: Scalars['UInt64'];
+ /** The id of the asset to add liquidity. */
+ assetId: Scalars['String'];
+ /** The id of the transfer. */
+ id: Scalars['String'];
+};
+
+export type AddPeerLiquidityInput = {
+ /** Amount of liquidity to add. */
+ amount: Scalars['UInt64'];
+ /** The id of the transfer. */
+ id: Scalars['String'];
+ /** The id of the peer to add liquidity. */
+ peerId: Scalars['String'];
+};
+
+export enum Alg {
+ EdDsa = 'EdDSA'
+}
+
+export type Amount = {
+ __typename?: 'Amount';
+ /** [ISO 4217 currency code](https://en.wikipedia.org/wiki/ISO_4217), e.g. `USD` */
+ assetCode: Scalars['String'];
+ /** Difference in orders of magnitude between the standard unit of an asset and a corresponding fractional unit */
+ assetScale: Scalars['UInt8'];
+ value: Scalars['UInt64'];
+};
+
+export type AmountInput = {
+ /** [ISO 4217 currency code](https://en.wikipedia.org/wiki/ISO_4217), e.g. `USD` */
+ assetCode: Scalars['String'];
+ /** Difference in orders of magnitude between the standard unit of an asset and a corresponding fractional unit */
+ assetScale: Scalars['UInt8'];
+ value: Scalars['UInt64'];
+};
+
+export type Asset = Model & {
+ __typename?: 'Asset';
+ /** [ISO 4217 currency code](https://en.wikipedia.org/wiki/ISO_4217), e.g. `USD` */
+ code: Scalars['String'];
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Asset id */
+ id: Scalars['ID'];
+ /** Difference in orders of magnitude between the standard unit of an asset and a corresponding fractional unit */
+ scale: Scalars['UInt8'];
+ /** Minimum amount of liquidity that can be withdrawn from the asset */
+ withdrawalThreshold?: Maybe;
+};
+
+export type AssetEdge = {
+ __typename?: 'AssetEdge';
+ cursor: Scalars['String'];
+ node: Asset;
+};
+
+export type AssetInput = {
+ /** [ISO 4217 currency code](https://en.wikipedia.org/wiki/ISO_4217), e.g. `USD` */
+ code: Scalars['String'];
+ /** Difference in orders of magnitude between the standard unit of an asset and a corresponding fractional unit */
+ scale: Scalars['UInt8'];
+};
+
+export type AssetMutationResponse = MutationResponse & {
+ __typename?: 'AssetMutationResponse';
+ asset?: Maybe;
+ code: Scalars['String'];
+ message: Scalars['String'];
+ success: Scalars['Boolean'];
+};
+
+export type AssetsConnection = {
+ __typename?: 'AssetsConnection';
+ edges: Array;
+ pageInfo: PageInfo;
+};
+
+export type CreateAssetInput = {
+ /** [ISO 4217 currency code](https://en.wikipedia.org/wiki/ISO_4217), e.g. `USD` */
+ code: Scalars['String'];
+ /** Difference in orders of magnitude between the standard unit of an asset and a corresponding fractional unit */
+ scale: Scalars['UInt8'];
+ /** Minimum amount of liquidity that can be withdrawn from the asset */
+ withdrawalThreshold?: InputMaybe;
+};
+
+export type CreateAssetLiquidityWithdrawalInput = {
+ /** Amount of withdrawal. */
+ amount: Scalars['UInt64'];
+ /** The id of the asset to create the withdrawal for. */
+ assetId: Scalars['String'];
+ /** The id of the withdrawal. */
+ id: Scalars['String'];
+};
+
+export type CreateIncomingPaymentInput = {
+ /** Human readable description of the incoming payment. */
+ description?: InputMaybe;
+ /** Expiration date-time */
+ expiresAt?: InputMaybe;
+ /** A reference that can be used by external systems to reconcile this payment with their systems. E.g. an invoice number. */
+ externalRef?: InputMaybe;
+ /** Maximum amount to be received */
+ incomingAmount?: InputMaybe;
+ /** Id of the payment pointer under which the incoming payment will be created */
+ paymentPointerId: Scalars['String'];
+};
+
+export type CreateOutgoingPaymentInput = {
+ /** Human readable description of the outgoing payment. */
+ description?: InputMaybe;
+ /** A reference that can be used by external systems to reconcile this payment with their systems. E.g. an invoice number. */
+ externalRef?: InputMaybe;
+ /** Id of the payment pointer under which the outgoing payment will be created */
+ paymentPointerId: Scalars['String'];
+ /** Id of the corresponding quote for that outgoing payment */
+ quoteId: Scalars['String'];
+};
+
+export type CreatePaymentPointerInput = {
+ /** Asset of the payment pointer */
+ assetId: Scalars['String'];
+ /** Public name associated with the payment pointer */
+ publicName?: InputMaybe;
+ /** Payment Pointer URL */
+ url: Scalars['String'];
+};
+
+export type CreatePaymentPointerKeyInput = {
+ /** Public key */
+ jwk: JwkInput;
+ paymentPointerId: Scalars['String'];
+};
+
+export type CreatePaymentPointerKeyMutationResponse = MutationResponse & {
+ __typename?: 'CreatePaymentPointerKeyMutationResponse';
+ code: Scalars['String'];
+ message: Scalars['String'];
+ paymentPointerKey?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export type CreatePaymentPointerMutationResponse = MutationResponse & {
+ __typename?: 'CreatePaymentPointerMutationResponse';
+ code: Scalars['String'];
+ message: Scalars['String'];
+ paymentPointer?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export type CreatePaymentPointerWithdrawalInput = {
+ /** The id of the withdrawal. */
+ id: Scalars['String'];
+ /** The id of the Open Payments payment pointer to create the withdrawal for. */
+ paymentPointerId: Scalars['String'];
+};
+
+export type CreatePeerInput = {
+ /** Asset id of peering relationship */
+ assetId: Scalars['String'];
+ /** Peering connection details */
+ http: HttpInput;
+ /** Maximum packet amount that the peer accepts */
+ maxPacketAmount?: InputMaybe;
+ /** Peer's internal name */
+ name?: InputMaybe;
+ /** Peer's ILP address */
+ staticIlpAddress: Scalars['String'];
+};
+
+export type CreatePeerLiquidityWithdrawalInput = {
+ /** Amount of withdrawal. */
+ amount: Scalars['UInt64'];
+ /** The id of the withdrawal. */
+ id: Scalars['String'];
+ /** The id of the peer to create the withdrawal for. */
+ peerId: Scalars['String'];
+};
+
+export type CreatePeerMutationResponse = MutationResponse & {
+ __typename?: 'CreatePeerMutationResponse';
+ code: Scalars['String'];
+ message: Scalars['String'];
+ peer?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export type CreateQuoteInput = {
+ /** Id of the payment pointer under which the quote will be created */
+ paymentPointerId: Scalars['String'];
+ /** Amount to receive (fixed receive) */
+ receiveAmount?: InputMaybe;
+ /** Payment pointer URL of the receiver */
+ receiver: Scalars['String'];
+ /** Amount to send (fixed send) */
+ sendAmount?: InputMaybe;
+};
+
+export type CreateReceiverInput = {
+ /** Human readable description of the incoming payment. */
+ description?: InputMaybe;
+ /** Expiration date-time */
+ expiresAt?: InputMaybe;
+ /** A reference that can be used by external systems to reconcile this payment with their systems. E.g. an invoice number. */
+ externalRef?: InputMaybe;
+ /** Maximum amount to be received */
+ incomingAmount?: InputMaybe;
+ /** Receiving payment pointer URL */
+ paymentPointerUrl: Scalars['String'];
+};
+
+export type CreateReceiverResponse = {
+ __typename?: 'CreateReceiverResponse';
+ code: Scalars['String'];
+ message?: Maybe;
+ receiver?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export enum Crv {
+ Ed25519 = 'Ed25519'
+}
+
+export type DeletePeerMutationResponse = MutationResponse & {
+ __typename?: 'DeletePeerMutationResponse';
+ code: Scalars['String'];
+ message: Scalars['String'];
+ success: Scalars['Boolean'];
+};
+
+export type Http = {
+ __typename?: 'Http';
+ /** Outgoing connection details */
+ outgoing: HttpOutgoing;
+};
+
+export type HttpIncomingInput = {
+ /** Array of auth tokens accepted by this Rafiki instance */
+ authTokens: Array;
+};
+
+export type HttpInput = {
+ /** Incoming connection details */
+ incoming?: InputMaybe;
+ /** Outgoing connection details */
+ outgoing: HttpOutgoingInput;
+};
+
+export type HttpOutgoing = {
+ __typename?: 'HttpOutgoing';
+ /** Auth token to present at the peering Rafiki instance */
+ authToken: Scalars['String'];
+ /** Peer's connection endpoint */
+ endpoint: Scalars['String'];
+};
+
+export type HttpOutgoingInput = {
+ /** Auth token to present at the peering Rafiki instance */
+ authToken: Scalars['String'];
+ /** Peer's connection endpoint */
+ endpoint: Scalars['String'];
+};
+
+export type IncomingPayment = Model & {
+ __typename?: 'IncomingPayment';
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Human readable description of the incoming payment. */
+ description?: Maybe;
+ /** Date-time of expiry. After this time, the incoming payment will not accept further payments made to it. */
+ expiresAt: Scalars['String'];
+ /** A reference that can be used by external systems to reconcile this payment with their systems. E.g. an invoice number. */
+ externalRef?: Maybe;
+ /** Incoming Payment id */
+ id: Scalars['ID'];
+ /** The maximum amount that should be paid into the payment pointer under this incoming payment. */
+ incomingAmount?: Maybe;
+ /** Id of the payment pointer under which this incoming payment was created */
+ paymentPointerId: Scalars['ID'];
+ /** The total amount that has been paid into the payment pointer under this incoming payment. */
+ receivedAmount: Amount;
+ /** Incoming payment state */
+ state: IncomingPaymentState;
+};
+
+export type IncomingPaymentConnection = {
+ __typename?: 'IncomingPaymentConnection';
+ edges: Array;
+ pageInfo: PageInfo;
+};
+
+export type IncomingPaymentEdge = {
+ __typename?: 'IncomingPaymentEdge';
+ cursor: Scalars['String'];
+ node: IncomingPayment;
+};
+
+export type IncomingPaymentResponse = {
+ __typename?: 'IncomingPaymentResponse';
+ code: Scalars['String'];
+ message?: Maybe;
+ payment?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export enum IncomingPaymentState {
+ /** The payment is either auto-completed once the received amount equals the expected `incomingAmount`, or it is completed manually via an API call. */
+ Completed = 'COMPLETED',
+ /** If the payment expires before it is completed then the state will move to EXPIRED and no further payments will be accepted. */
+ Expired = 'EXPIRED',
+ /** The payment has a state of PENDING when it is initially created. */
+ Pending = 'PENDING',
+ /** As soon as payment has started (funds have cleared into the account) the state moves to PROCESSING */
+ Processing = 'PROCESSING'
+}
+
+export type Jwk = {
+ __typename?: 'Jwk';
+ /** Cryptographic algorithm family used with the key. The only allowed value is `EdDSA`. */
+ alg: Alg;
+ /** Curve that the key pair is derived from. The only allowed value is `Ed25519`. */
+ crv: Crv;
+ /** Key id */
+ kid: Scalars['String'];
+ /** Key type. The only allowed value is `OKP`. */
+ kty: Kty;
+ /** Base64 url-encoded public key. */
+ x: Scalars['String'];
+};
+
+export type JwkInput = {
+ /** Cryptographic algorithm family used with the key. The only allowed value is `EdDSA`. */
+ alg: Alg;
+ /** Curve that the key pair is derived from. The only allowed value is `Ed25519`. */
+ crv: Crv;
+ /** Key id */
+ kid: Scalars['String'];
+ /** Key type. The only allowed value is `OKP`. */
+ kty: Kty;
+ /** Base64 url-encoded public key. */
+ x: Scalars['String'];
+};
+
+export enum Kty {
+ Okp = 'OKP'
+}
+
+export enum LiquidityError {
+ AlreadyPosted = 'AlreadyPosted',
+ AlreadyVoided = 'AlreadyVoided',
+ AmountZero = 'AmountZero',
+ InsufficientBalance = 'InsufficientBalance',
+ InvalidId = 'InvalidId',
+ TransferExists = 'TransferExists',
+ UnknownAsset = 'UnknownAsset',
+ UnknownIncomingPayment = 'UnknownIncomingPayment',
+ UnknownPayment = 'UnknownPayment',
+ UnknownPaymentPointer = 'UnknownPaymentPointer',
+ UnknownPeer = 'UnknownPeer',
+ UnknownTransfer = 'UnknownTransfer'
+}
+
+export type LiquidityMutationResponse = MutationResponse & {
+ __typename?: 'LiquidityMutationResponse';
+ code: Scalars['String'];
+ error?: Maybe;
+ message: Scalars['String'];
+ success: Scalars['Boolean'];
+};
+
+export type Model = {
+ createdAt: Scalars['String'];
+ id: Scalars['ID'];
+};
+
+export type Mutation = {
+ __typename?: 'Mutation';
+ /** Add asset liquidity */
+ addAssetLiquidity?: Maybe;
+ /** Add peer liquidity */
+ addPeerLiquidity?: Maybe;
+ /** Create an asset */
+ createAsset: AssetMutationResponse;
+ /** Withdraw asset liquidity */
+ createAssetLiquidityWithdrawal?: Maybe;
+ /** Create an internal Open Payments Incoming Payment. The receiver has a payment pointer on this Rafiki instance. */
+ createIncomingPayment: IncomingPaymentResponse;
+ /** Create an Open Payments Outgoing Payment */
+ createOutgoingPayment: OutgoingPaymentResponse;
+ /** Create a payment pointer */
+ createPaymentPointer: CreatePaymentPointerMutationResponse;
+ /** Add a public key to a payment pointer that is used to verify Open Payments requests. */
+ createPaymentPointerKey?: Maybe;
+ /** Withdraw liquidity from a payment pointer received via Web Monetization. */
+ createPaymentPointerWithdrawal?: Maybe;
+ /** Create a peer */
+ createPeer: CreatePeerMutationResponse;
+ /** Withdraw peer liquidity */
+ createPeerLiquidityWithdrawal?: Maybe;
+ /** Create an Open Payments Quote */
+ createQuote: QuoteResponse;
+ /** Create an internal or external Open Payments Incoming Payment. The receiver has a payment pointer on either this or another Open Payments resource server. */
+ createReceiver: CreateReceiverResponse;
+ /** Delete a peer */
+ deletePeer: DeletePeerMutationResponse;
+ /** Deposit webhook event liquidity */
+ depositEventLiquidity?: Maybe;
+ /** Post liquidity withdrawal. Withdrawals are two-phase commits and are committed via this mutation. */
+ postLiquidityWithdrawal?: Maybe;
+ /** Revoke a public key associated with a payment pointer. Open Payment requests using this key for request signatures will be denied going forward. */
+ revokePaymentPointerKey?: Maybe;
+ /** If automatic withdrawal of funds received via Web Monetization by the payment pointer are disabled, this mutation can be used to trigger up to n withdrawal events. */
+ triggerPaymentPointerEvents: TriggerPaymentPointerEventsMutationResponse;
+ /** Update an asset's withdrawal threshold. The withdrawal threshold indicates the MINIMUM amount that can be withdrawn. */
+ updateAssetWithdrawalThreshold: AssetMutationResponse;
+ /** Update a peer */
+ updatePeer: UpdatePeerMutationResponse;
+ /** Void liquidity withdrawal. Withdrawals are two-phase commits and are rolled back via this mutation. */
+ voidLiquidityWithdrawal?: Maybe;
+ /** Withdraw webhook event liquidity */
+ withdrawEventLiquidity?: Maybe;
+};
+
+
+export type MutationAddAssetLiquidityArgs = {
+ input: AddAssetLiquidityInput;
+};
+
+
+export type MutationAddPeerLiquidityArgs = {
+ input: AddPeerLiquidityInput;
+};
+
+
+export type MutationCreateAssetArgs = {
+ input: CreateAssetInput;
+};
+
+
+export type MutationCreateAssetLiquidityWithdrawalArgs = {
+ input: CreateAssetLiquidityWithdrawalInput;
+};
+
+
+export type MutationCreateIncomingPaymentArgs = {
+ input: CreateIncomingPaymentInput;
+};
+
+
+export type MutationCreateOutgoingPaymentArgs = {
+ input: CreateOutgoingPaymentInput;
+};
+
+
+export type MutationCreatePaymentPointerArgs = {
+ input: CreatePaymentPointerInput;
+};
+
+
+export type MutationCreatePaymentPointerKeyArgs = {
+ input: CreatePaymentPointerKeyInput;
+};
+
+
+export type MutationCreatePaymentPointerWithdrawalArgs = {
+ input: CreatePaymentPointerWithdrawalInput;
+};
+
+
+export type MutationCreatePeerArgs = {
+ input: CreatePeerInput;
+};
+
+
+export type MutationCreatePeerLiquidityWithdrawalArgs = {
+ input: CreatePeerLiquidityWithdrawalInput;
+};
+
+
+export type MutationCreateQuoteArgs = {
+ input: CreateQuoteInput;
+};
+
+
+export type MutationCreateReceiverArgs = {
+ input: CreateReceiverInput;
+};
+
+
+export type MutationDeletePeerArgs = {
+ id: Scalars['String'];
+};
+
+
+export type MutationDepositEventLiquidityArgs = {
+ eventId: Scalars['String'];
+};
+
+
+export type MutationPostLiquidityWithdrawalArgs = {
+ withdrawalId: Scalars['String'];
+};
+
+
+export type MutationRevokePaymentPointerKeyArgs = {
+ id: Scalars['String'];
+};
+
+
+export type MutationTriggerPaymentPointerEventsArgs = {
+ limit: Scalars['Int'];
+};
+
+
+export type MutationUpdateAssetWithdrawalThresholdArgs = {
+ input: UpdateAssetInput;
+};
+
+
+export type MutationUpdatePeerArgs = {
+ input: UpdatePeerInput;
+};
+
+
+export type MutationVoidLiquidityWithdrawalArgs = {
+ withdrawalId: Scalars['String'];
+};
+
+
+export type MutationWithdrawEventLiquidityArgs = {
+ eventId: Scalars['String'];
+};
+
+export type MutationResponse = {
+ code: Scalars['String'];
+ message: Scalars['String'];
+ success: Scalars['Boolean'];
+};
+
+export type OutgoingPayment = Model & {
+ __typename?: 'OutgoingPayment';
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Human readable description of the outgoing payment. */
+ description?: Maybe;
+ error?: Maybe;
+ /** A reference that can be used by external systems to reconcile this payment with their systems. E.g. an invoice number. */
+ externalRef?: Maybe;
+ /** Outgoing payment id */
+ id: Scalars['ID'];
+ /** Id of the payment pointer under which this outgoing payment was created */
+ paymentPointerId: Scalars['ID'];
+ /** Quote for this outgoing payment */
+ quote?: Maybe;
+ /** Amount to receive (fixed receive) */
+ receiveAmount: Amount;
+ /** Payment pointer URL of the receiver */
+ receiver: Scalars['String'];
+ /** Amount to send (fixed send) */
+ sendAmount: Amount;
+ /** Amount already sent */
+ sentAmount: Amount;
+ /** Outgoing payment state */
+ state: OutgoingPaymentState;
+ stateAttempts: Scalars['Int'];
+};
+
+export type OutgoingPaymentConnection = {
+ __typename?: 'OutgoingPaymentConnection';
+ edges: Array;
+ pageInfo: PageInfo;
+};
+
+export type OutgoingPaymentEdge = {
+ __typename?: 'OutgoingPaymentEdge';
+ cursor: Scalars['String'];
+ node: OutgoingPayment;
+};
+
+export type OutgoingPaymentResponse = {
+ __typename?: 'OutgoingPaymentResponse';
+ code: Scalars['String'];
+ message?: Maybe;
+ payment?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export enum OutgoingPaymentState {
+ /** Successful completion */
+ Completed = 'COMPLETED',
+ /** Payment failed */
+ Failed = 'FAILED',
+ /** Will transition to SENDING once payment funds are reserved */
+ Funding = 'FUNDING',
+ /** Paying, will transition to COMPLETED on success */
+ Sending = 'SENDING'
+}
+
+export type PageInfo = {
+ __typename?: 'PageInfo';
+ /** Paginating forwards: the cursor to continue. */
+ endCursor?: Maybe;
+ /** Paginating forwards: Are there more pages? */
+ hasNextPage: Scalars['Boolean'];
+ /** Paginating backwards: Are there more pages? */
+ hasPreviousPage: Scalars['Boolean'];
+ /** Paginating backwards: the cursor to continue. */
+ startCursor?: Maybe;
+};
+
+export type PaymentPointer = Model & {
+ __typename?: 'PaymentPointer';
+ /** Asset of the payment pointer */
+ asset: Asset;
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Payment pointer id */
+ id: Scalars['ID'];
+ /** List of incoming payments received by this payment pointer */
+ incomingPayments?: Maybe;
+ /** List of outgoing payments sent from this payment pointer */
+ outgoingPayments?: Maybe;
+ /** Public name associated with the payment pointer */
+ publicName?: Maybe;
+ /** List of quotes created at this payment pointer */
+ quotes?: Maybe;
+ /** Payment Pointer URL */
+ url: Scalars['String'];
+};
+
+
+export type PaymentPointerIncomingPaymentsArgs = {
+ after?: InputMaybe;
+ before?: InputMaybe;
+ first?: InputMaybe;
+ last?: InputMaybe;
+};
+
+
+export type PaymentPointerOutgoingPaymentsArgs = {
+ after?: InputMaybe;
+ before?: InputMaybe;
+ first?: InputMaybe;
+ last?: InputMaybe;
+};
+
+
+export type PaymentPointerQuotesArgs = {
+ after?: InputMaybe;
+ before?: InputMaybe;
+ first?: InputMaybe;
+ last?: InputMaybe;
+};
+
+export type PaymentPointerKey = Model & {
+ __typename?: 'PaymentPointerKey';
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Internal id of key */
+ id: Scalars['ID'];
+ /** Public key */
+ jwk: Jwk;
+ /** Id of the payment pointer to which this key belongs to */
+ paymentPointerId: Scalars['ID'];
+ /** Indicator whether the key has been revoked */
+ revoked: Scalars['Boolean'];
+};
+
+export type PaymentPointerWithdrawal = {
+ __typename?: 'PaymentPointerWithdrawal';
+ /** Amount to withdraw */
+ amount: Scalars['UInt64'];
+ /** Withdrawal Id */
+ id: Scalars['ID'];
+ /** Payment pointer details */
+ paymentPointer: PaymentPointer;
+};
+
+export type PaymentPointerWithdrawalMutationResponse = MutationResponse & {
+ __typename?: 'PaymentPointerWithdrawalMutationResponse';
+ code: Scalars['String'];
+ error?: Maybe;
+ message: Scalars['String'];
+ success: Scalars['Boolean'];
+ withdrawal?: Maybe;
+};
+
+export type Peer = Model & {
+ __typename?: 'Peer';
+ /** Asset of peering relationship */
+ asset: Asset;
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Peering connection details */
+ http: Http;
+ /** Peer id */
+ id: Scalars['ID'];
+ /** Maximum packet amount that the peer accepts */
+ maxPacketAmount?: Maybe;
+ /** Peer's public name */
+ name?: Maybe;
+ /** Peer's ILP address */
+ staticIlpAddress: Scalars['String'];
+};
+
+export type PeerEdge = {
+ __typename?: 'PeerEdge';
+ cursor: Scalars['String'];
+ node: Peer;
+};
+
+export type PeersConnection = {
+ __typename?: 'PeersConnection';
+ edges: Array;
+ pageInfo: PageInfo;
+};
+
+export type Query = {
+ __typename?: 'Query';
+ /** Fetch an asset */
+ asset?: Maybe;
+ /** Fetch a page of assets. */
+ assets: AssetsConnection;
+ /** Fetch an Open Payments outgoing payment */
+ outgoingPayment?: Maybe;
+ /** Fetch a payment pointer */
+ paymentPointer?: Maybe;
+ /** Fetch a peer */
+ peer?: Maybe;
+ /** Fetch a page of peers. */
+ peers: PeersConnection;
+ /** Fetch an Open Payments quote */
+ quote?: Maybe;
+};
+
+
+export type QueryAssetArgs = {
+ id: Scalars['String'];
+};
+
+
+export type QueryAssetsArgs = {
+ after?: InputMaybe;
+ before?: InputMaybe;
+ first?: InputMaybe;
+ last?: InputMaybe;
+};
+
+
+export type QueryOutgoingPaymentArgs = {
+ id: Scalars['String'];
+};
+
+
+export type QueryPaymentPointerArgs = {
+ id: Scalars['String'];
+};
+
+
+export type QueryPeerArgs = {
+ id: Scalars['String'];
+};
+
+
+export type QueryPeersArgs = {
+ after?: InputMaybe;
+ before?: InputMaybe;
+ first?: InputMaybe;
+ last?: InputMaybe;
+};
+
+
+export type QueryQuoteArgs = {
+ id: Scalars['String'];
+};
+
+export type Quote = {
+ __typename?: 'Quote';
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Date-time of expiration */
+ expiresAt: Scalars['String'];
+ /** Upper bound of probed exchange rate */
+ highEstimatedExchangeRate: Scalars['Float'];
+ /** Quote id */
+ id: Scalars['ID'];
+ /** Lower bound of probed exchange rate */
+ lowEstimatedExchangeRate: Scalars['Float'];
+ /** Maximum value per packet allowed on the possible routes */
+ maxPacketAmount: Scalars['UInt64'];
+ /** Aggregate exchange rate the payment is guaranteed to meet */
+ minExchangeRate: Scalars['Float'];
+ /** Id of the payment pointer under which this quote was created */
+ paymentPointerId: Scalars['ID'];
+ /** Amount to receive (fixed receive) */
+ receiveAmount: Amount;
+ /** Payment pointer URL of the receiver */
+ receiver: Scalars['String'];
+ /** Amount to send (fixed send) */
+ sendAmount: Amount;
+};
+
+export type QuoteConnection = {
+ __typename?: 'QuoteConnection';
+ edges: Array;
+ pageInfo: PageInfo;
+};
+
+export type QuoteEdge = {
+ __typename?: 'QuoteEdge';
+ cursor: Scalars['String'];
+ node: Quote;
+};
+
+export type QuoteResponse = {
+ __typename?: 'QuoteResponse';
+ code: Scalars['String'];
+ message?: Maybe;
+ quote?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export type Receiver = {
+ __typename?: 'Receiver';
+ /** Describes whether the incoming payment has completed receiving funds. */
+ completed: Scalars['Boolean'];
+ /** Date-time of creation */
+ createdAt: Scalars['String'];
+ /** Human readable description of the incoming payment. */
+ description?: Maybe;
+ /** Date-time of expiry. After this time, the incoming payment will accept further payments made to it. */
+ expiresAt?: Maybe;
+ /** A reference that can be used by external systems to reconcile this payment with their systems. E.g. an invoice number. */
+ externalRef?: Maybe;
+ /** Incoming payment URL */
+ id: Scalars['String'];
+ /** The maximum amount that should be paid into the payment pointer under this incoming payment. */
+ incomingAmount?: Maybe;
+ /** Payment pointer URL under which the incoming payment was created */
+ paymentPointerUrl: Scalars['String'];
+ /** The total amount that has been paid into the payment pointer under this incoming payment. */
+ receivedAmount: Amount;
+ /** Date-time of last update */
+ updatedAt: Scalars['String'];
+};
+
+export type RevokePaymentPointerKeyMutationResponse = MutationResponse & {
+ __typename?: 'RevokePaymentPointerKeyMutationResponse';
+ code: Scalars['String'];
+ message: Scalars['String'];
+ paymentPointerKey?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+export type TransferMutationResponse = MutationResponse & {
+ __typename?: 'TransferMutationResponse';
+ code: Scalars['String'];
+ message: Scalars['String'];
+ success: Scalars['Boolean'];
+};
+
+export type TriggerPaymentPointerEventsMutationResponse = MutationResponse & {
+ __typename?: 'TriggerPaymentPointerEventsMutationResponse';
+ code: Scalars['String'];
+ /** Number of events triggered */
+ count?: Maybe;
+ message: Scalars['String'];
+ success: Scalars['Boolean'];
+};
+
+export type UpdateAssetInput = {
+ /** Asset id */
+ id: Scalars['String'];
+ /** New minimum amount of liquidity that can be withdrawn from the asset */
+ withdrawalThreshold?: InputMaybe;
+};
+
+export type UpdatePeerInput = {
+ /** New peering connection details */
+ http?: InputMaybe;
+ /** Peer id */
+ id: Scalars['String'];
+ /** New maximum packet amount that the peer accepts */
+ maxPacketAmount?: InputMaybe;
+ /** Peer's new public name */
+ name?: InputMaybe;
+ /** Peer's new ILP address */
+ staticIlpAddress?: InputMaybe;
+};
+
+export type UpdatePeerMutationResponse = MutationResponse & {
+ __typename?: 'UpdatePeerMutationResponse';
+ code: Scalars['String'];
+ message: Scalars['String'];
+ peer?: Maybe;
+ success: Scalars['Boolean'];
+};
+
+
+
+export type ResolverTypeWrapper = Promise | T;
+
+
+export type ResolverWithResolve = {
+ resolve: ResolverFn;
+};
+export type Resolver = ResolverFn | ResolverWithResolve;
+
+export type ResolverFn = (
+ parent: TParent,
+ args: TArgs,
+ context: TContext,
+ info: GraphQLResolveInfo
+) => Promise | TResult;
+
+export type SubscriptionSubscribeFn = (
+ parent: TParent,
+ args: TArgs,
+ context: TContext,
+ info: GraphQLResolveInfo
+) => AsyncIterable | Promise>;
+
+export type SubscriptionResolveFn = (
+ parent: TParent,
+ args: TArgs,
+ context: TContext,
+ info: GraphQLResolveInfo
+) => TResult | Promise;
+
+export interface SubscriptionSubscriberObject {
+ subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>;
+ resolve?: SubscriptionResolveFn;
+}
+
+export interface SubscriptionResolverObject {
+ subscribe: SubscriptionSubscribeFn;
+ resolve: SubscriptionResolveFn;
+}
+
+export type SubscriptionObject =
+ | SubscriptionSubscriberObject
+ | SubscriptionResolverObject;
+
+export type SubscriptionResolver =
+ | ((...args: any[]) => SubscriptionObject)
+ | SubscriptionObject;
+
+export type TypeResolveFn = (
+ parent: TParent,
+ context: TContext,
+ info: GraphQLResolveInfo
+) => Maybe | Promise>;
+
+export type IsTypeOfResolverFn = (obj: T, context: TContext, info: GraphQLResolveInfo) => boolean | Promise;
+
+export type NextResolverFn = () => Promise;
+
+export type DirectiveResolverFn = (
+ next: NextResolverFn,
+ parent: TParent,
+ args: TArgs,
+ context: TContext,
+ info: GraphQLResolveInfo
+) => TResult | Promise;
+
+
+/** Mapping between all available schema types and the resolvers types */
+export type ResolversTypes = {
+ AddAssetLiquidityInput: ResolverTypeWrapper>;
+ AddPeerLiquidityInput: ResolverTypeWrapper>;
+ Alg: ResolverTypeWrapper>;
+ Amount: ResolverTypeWrapper>;
+ AmountInput: ResolverTypeWrapper>;
+ Asset: ResolverTypeWrapper>;
+ AssetEdge: ResolverTypeWrapper>;
+ AssetInput: ResolverTypeWrapper>;
+ AssetMutationResponse: ResolverTypeWrapper>;
+ AssetsConnection: ResolverTypeWrapper>;
+ Boolean: ResolverTypeWrapper>;
+ CreateAssetInput: ResolverTypeWrapper>;
+ CreateAssetLiquidityWithdrawalInput: ResolverTypeWrapper>;
+ CreateIncomingPaymentInput: ResolverTypeWrapper>;
+ CreateOutgoingPaymentInput: ResolverTypeWrapper>;
+ CreatePaymentPointerInput: ResolverTypeWrapper>;
+ CreatePaymentPointerKeyInput: ResolverTypeWrapper>;
+ CreatePaymentPointerKeyMutationResponse: ResolverTypeWrapper>;
+ CreatePaymentPointerMutationResponse: ResolverTypeWrapper>;
+ CreatePaymentPointerWithdrawalInput: ResolverTypeWrapper>;
+ CreatePeerInput: ResolverTypeWrapper>;
+ CreatePeerLiquidityWithdrawalInput: ResolverTypeWrapper>;
+ CreatePeerMutationResponse: ResolverTypeWrapper>;
+ CreateQuoteInput: ResolverTypeWrapper>;
+ CreateReceiverInput: ResolverTypeWrapper>;
+ CreateReceiverResponse: ResolverTypeWrapper>;
+ Crv: ResolverTypeWrapper>;
+ DeletePeerMutationResponse: ResolverTypeWrapper>;
+ Float: ResolverTypeWrapper>;
+ Http: ResolverTypeWrapper>;
+ HttpIncomingInput: ResolverTypeWrapper>;
+ HttpInput: ResolverTypeWrapper>;
+ HttpOutgoing: ResolverTypeWrapper>;
+ HttpOutgoingInput: ResolverTypeWrapper>;
+ ID: ResolverTypeWrapper>;
+ IncomingPayment: ResolverTypeWrapper>;
+ IncomingPaymentConnection: ResolverTypeWrapper>;
+ IncomingPaymentEdge: ResolverTypeWrapper>;
+ IncomingPaymentResponse: ResolverTypeWrapper>;
+ IncomingPaymentState: ResolverTypeWrapper>;
+ Int: ResolverTypeWrapper>;
+ Jwk: ResolverTypeWrapper>;
+ JwkInput: ResolverTypeWrapper>;
+ Kty: ResolverTypeWrapper>;
+ LiquidityError: ResolverTypeWrapper>;
+ LiquidityMutationResponse: ResolverTypeWrapper>;
+ Model: ResolversTypes['Asset'] | ResolversTypes['IncomingPayment'] | ResolversTypes['OutgoingPayment'] | ResolversTypes['PaymentPointer'] | ResolversTypes['PaymentPointerKey'] | ResolversTypes['Peer'];
+ Mutation: ResolverTypeWrapper<{}>;
+ MutationResponse: ResolversTypes['AssetMutationResponse'] | ResolversTypes['CreatePaymentPointerKeyMutationResponse'] | ResolversTypes['CreatePaymentPointerMutationResponse'] | ResolversTypes['CreatePeerMutationResponse'] | ResolversTypes['DeletePeerMutationResponse'] | ResolversTypes['LiquidityMutationResponse'] | ResolversTypes['PaymentPointerWithdrawalMutationResponse'] | ResolversTypes['RevokePaymentPointerKeyMutationResponse'] | ResolversTypes['TransferMutationResponse'] | ResolversTypes['TriggerPaymentPointerEventsMutationResponse'] | ResolversTypes['UpdatePeerMutationResponse'];
+ OutgoingPayment: ResolverTypeWrapper>;
+ OutgoingPaymentConnection: ResolverTypeWrapper>;
+ OutgoingPaymentEdge: ResolverTypeWrapper>;
+ OutgoingPaymentResponse: ResolverTypeWrapper>;
+ OutgoingPaymentState: ResolverTypeWrapper>;
+ PageInfo: ResolverTypeWrapper>;
+ PaymentPointer: ResolverTypeWrapper>;
+ PaymentPointerKey: ResolverTypeWrapper>;
+ PaymentPointerWithdrawal: ResolverTypeWrapper>;
+ PaymentPointerWithdrawalMutationResponse: ResolverTypeWrapper>;
+ Peer: ResolverTypeWrapper>;
+ PeerEdge: ResolverTypeWrapper>;
+ PeersConnection: ResolverTypeWrapper>;
+ Query: ResolverTypeWrapper<{}>;
+ Quote: ResolverTypeWrapper>;
+ QuoteConnection: ResolverTypeWrapper>;
+ QuoteEdge: ResolverTypeWrapper>;
+ QuoteResponse: ResolverTypeWrapper>;
+ Receiver: ResolverTypeWrapper>;
+ RevokePaymentPointerKeyMutationResponse: ResolverTypeWrapper>;
+ String: ResolverTypeWrapper>;
+ TransferMutationResponse: ResolverTypeWrapper>;
+ TriggerPaymentPointerEventsMutationResponse: ResolverTypeWrapper>;
+ UInt8: ResolverTypeWrapper>;
+ UInt64: ResolverTypeWrapper>;
+ UpdateAssetInput: ResolverTypeWrapper>;
+ UpdatePeerInput: ResolverTypeWrapper>;
+ UpdatePeerMutationResponse: ResolverTypeWrapper>;
+};
+
+/** Mapping between all available schema types and the resolvers parents */
+export type ResolversParentTypes = {
+ AddAssetLiquidityInput: Partial;
+ AddPeerLiquidityInput: Partial;
+ Amount: Partial;
+ AmountInput: Partial;
+ Asset: Partial;
+ AssetEdge: Partial;
+ AssetInput: Partial;
+ AssetMutationResponse: Partial;
+ AssetsConnection: Partial;
+ Boolean: Partial;
+ CreateAssetInput: Partial;
+ CreateAssetLiquidityWithdrawalInput: Partial