From a62092ab640e337d643e34dbe43f7de696e7a93e Mon Sep 17 00:00:00 2001 From: Anton Adamkovich Date: Mon, 27 Mar 2023 01:33:11 -0700 Subject: [PATCH 1/9] update project structure --- content-new/docs/api.mdx | 7 + content-new/docs/api/getting-started.mdx | 331 ++++++++++++++++++ content-new/docs/api/overview.mdx | 8 + content-new/docs/api/parameters.json | 38 ++ content-new/docs/api/parameters.ts | 9 + content-new/docs/api/support-lify-cycle.mdx | 24 ++ content-new/docs/api/versioning.mdx | 17 + content-new/docs/embedded-banking.mdx | 7 + .../fscs-protected-deposits.mdx | 59 ++++ .../retail-customers.constants.tsx | 9 + content-new/docs/gbp-accounts.mdx | 7 + .../docs/gbp-accounts/account-types.mdx | 31 ++ .../docs/gbp-accounts/bacs-payment-data.mdx | 4 + .../docs/gbp-accounts/manage-accounts.mdx | 174 +++++++++ .../docs/gbp-accounts/payment-data.mdx | 4 + .../gbp-accounts/real-accounts.constants.tsx | 9 + .../virtual-accounts.constants.tsx | 10 + content-new/docs/index.mdx | 6 + content-new/docs/multi-currency.mdx | 7 + .../docs/multi-currency/account-reporting.mdx | 4 + content-new/docs/multi-currency/fx-trade.mdx | 4 + .../manage-multi-currency-accounts.mdx | 4 + .../multi-currency-account-types.mdx | 4 + .../multi-currency-payments.mdx | 4 + content-new/docs/uk-payments.mdx | 7 + .../bacs-direct-debit-instructions.mdx | 4 + content-new/docs/uk-payments/bacs.mdx | 4 + content-new/docs/uk-payments/chaps.mdx | 4 + .../uk-payments/confirmation-of-payee.mdx | 4 + .../docs/uk-payments/faster-payments.mdx | 4 + .../docs/uk-payments/internal-transfers.mdx | 4 + gatsby-config.js | 4 +- package-lock.json | 1 + package.json | 1 + .../header-menu/header-menu.styles.ts | 77 ++++ src/components/header-menu/header-menu.tsx | 22 ++ .../header-menu/header-sub-menu.tsx | 44 +++ src/components/header-menu/index.ts | 1 + src/components/header/header.tsx | 2 +- src/components/layout/layout.styles.ts | 8 +- src/components/layout/layout.tsx | 9 +- src/components/theme.ts | 3 +- 42 files changed, 971 insertions(+), 13 deletions(-) create mode 100644 content-new/docs/api.mdx create mode 100644 content-new/docs/api/getting-started.mdx create mode 100644 content-new/docs/api/overview.mdx create mode 100644 content-new/docs/api/parameters.json create mode 100644 content-new/docs/api/parameters.ts create mode 100644 content-new/docs/api/support-lify-cycle.mdx create mode 100644 content-new/docs/api/versioning.mdx create mode 100644 content-new/docs/embedded-banking.mdx create mode 100644 content-new/docs/embedded-banking/fscs-protected-deposits.mdx create mode 100644 content-new/docs/embedded-banking/retail-customers.constants.tsx create mode 100644 content-new/docs/gbp-accounts.mdx create mode 100644 content-new/docs/gbp-accounts/account-types.mdx create mode 100644 content-new/docs/gbp-accounts/bacs-payment-data.mdx create mode 100644 content-new/docs/gbp-accounts/manage-accounts.mdx create mode 100644 content-new/docs/gbp-accounts/payment-data.mdx create mode 100644 content-new/docs/gbp-accounts/real-accounts.constants.tsx create mode 100644 content-new/docs/gbp-accounts/virtual-accounts.constants.tsx create mode 100644 content-new/docs/index.mdx create mode 100644 content-new/docs/multi-currency.mdx create mode 100644 content-new/docs/multi-currency/account-reporting.mdx create mode 100644 content-new/docs/multi-currency/fx-trade.mdx create mode 100644 content-new/docs/multi-currency/manage-multi-currency-accounts.mdx create mode 100644 content-new/docs/multi-currency/multi-currency-account-types.mdx create mode 100644 content-new/docs/multi-currency/multi-currency-payments.mdx create mode 100644 content-new/docs/uk-payments.mdx create mode 100644 content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx create mode 100644 content-new/docs/uk-payments/bacs.mdx create mode 100644 content-new/docs/uk-payments/chaps.mdx create mode 100644 content-new/docs/uk-payments/confirmation-of-payee.mdx create mode 100644 content-new/docs/uk-payments/faster-payments.mdx create mode 100644 content-new/docs/uk-payments/internal-transfers.mdx create mode 100644 src/components/header-menu/header-menu.styles.ts create mode 100644 src/components/header-menu/header-menu.tsx create mode 100644 src/components/header-menu/header-sub-menu.tsx create mode 100644 src/components/header-menu/index.ts diff --git a/content-new/docs/api.mdx b/content-new/docs/api.mdx new file mode 100644 index 000000000..793a1a03d --- /dev/null +++ b/content-new/docs/api.mdx @@ -0,0 +1,7 @@ +--- +title: "API" +order: 1 +metaTitle: "API" +metaDescription: "" +showPageMenu: true +--- \ No newline at end of file diff --git a/content-new/docs/api/getting-started.mdx b/content-new/docs/api/getting-started.mdx new file mode 100644 index 000000000..7448efe9b --- /dev/null +++ b/content-new/docs/api/getting-started.mdx @@ -0,0 +1,331 @@ +--- +title: "Getting started" +order: 2 +--- + +import EndpointBlock from "src/components/endpoint-block"; + +## Get connected + +Before you can integrate with our API, you need to have been onboarded by us as a customer and have a valid authentication profile set up. +This authentication profile includes your Digital Certificate and secure API token. The API token needs to be included in the header of all REST API calls. +You can find information about how to generate these in our [introduction section](/docs/introduction). + +## Use endpoints + +### Common Parameters + +We utilise HTTP-request headers for our API calls which include `Authorization`, `DigitalSignature` and `X-Request-Id` headers. In all our responses we will send an `X-Correlation-Id` in the header. + +`GET` requests have an `Authorization` header. + +NON-GET requests such as `POST`, `PATCH` and `DELETE` have an `Authorization` header. + +import ParameterDetails from 'src/components/parameter-details' +import parameters from './parameters.json' + + + + + + +### Authenticate your API calls + +We use your API token to authenticate your requests and allow you to securely access protected resources. + +The base URL for your environment is either: +- Simulation `https://institution-api-sim.clearbank.co.uk/` +- Production `https://institution-api.clearbank.co.uk/` + +Your API token should be included in your HTTP `Authorization` header. Please refer to [Common Parameters](#common-parameters]) for more information. + +This example request shows the API token in the `Authorization` , `DigitalSignature` and `X-Request-Id` header. + +``` json +curl -v -POST https://institution-api-sim.clearbank.co.uk/v1/Test \ + -H “Authorization: Bearer <>” + -H “DigitalSignature: <>” + -H “X-Request-Id: <>”      + -d ‘{ "body": "hello world!" }’       +``` + +The response shows results from the test call +``` json +{ + "Message": "hello world!" +} +``` + +To confirm that authentication and signature verification are working as expected, when you send a POST/v1/Test request you will receive a `FITestEvent webhook` from ClearBank® (if you are subscribed to it). +We use webhooks to deliver transaction confirmation notifications and account-specific reconciliations to your system as soon as such events occur on your account. Please refer to [Test Webhooks](/webhooks/) for more information. + +#### TEST Endpoints + + + + + +### Query Parameters + +For most of our `GET` requests, one or more query parameters in the request URL can be used to specify the number of returned results and the number of pages returned. + +| Parameter | Type | Description | +|--------------|------|-------------------------------------------------------------------------------------------------------------| +| `pageNumber` | int | The page number to control returned results into manageable sets. Default if not supplied: 1 `pageNumber=1` | +| `pageSize` | int | The page size to control returned results into manageable sets. Default if not supplied: 50 `pageSize=50` | + +### HTTP Status Codes + +ClearBank® requests return a HTTP status code to indicate the success or failure of a request. For successful requests, we return a HTTP `2XX` status code. For failed requests, we return a HTTP `4XX` or `5XX` status code. Some endpoints return JSON response bodies that include errors and additional properties. + + +| Status Code | Description | +|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| `200` | Success! | +| `201` | Success! | +| `202` | Request received successfully and is being processed | +| `400` | Bad request. Something went wrong with the request. The response should include the reason why the request has failed | +| `403` | Forbidden. Your API token does not have permissions to perform the request | +| `404` | Not found. The resource you are looking for cannot be found | +| `409` | Conflict. A request conflict with the current state of the server +| `429` | Too many requests. You have sent too many requests in a given time ("rate limiting") | +| `500` | Internal server error | +| `503` | Server error. Service unavailable | + + +#### 5xx status codes +If you receive a 5xx error code, you should retry your request as these are service errors. A request that returns these errors may, in exceptional circumstances, result in being processed regardless. Following which, you will receive a notification (webhook) delivered to you as expected. + +To avoid any duplication, always retry all such requests with exactly the same request Id header and payload. If the initial request is successful, the retry request will trigger a notification (HTTP response or webhook) to confirm that it has not been processed as it was identified as a duplicate. + +#### Example of a response containing detailed errors + +```json +{ + "errors": { + "additionalProp1": [ + "string" + ], + "additionalProp2": [ + "string" + ], + "additionalProp3": [ + "string" + ] + }, + "type": "string", + "title": "string", + "status": 0, + "detail": "string", + "instance": "string" +} +``` + +### HAL Links + +We use HAL (Hypertext Application Language) to hyperlink between resources in our API. + +Each HAL hyperlink contains: + +| Parameter | Type | Required | Description | +|-------------|-----------|----------|---------------------------------------------------------------------------------------------------------------------------| +| `name` | `string` | Required | The named link type | +| `href` | `string` | Required | URI to be used | +| `templated` | `boolean` | | Specified as `true` if href is a URI template, i.e. with parameters. Otherwise, this property is absent or set to `false` | + +#### Example HAL Links +```json +{ + "accounts": [ + { + "id": "9140d28b-58d4-4e14-a5fe-43a655c82162", + "name": "Gen Seg Acc Wsale - TradingBankEnd2End", + "type": "CACC", + "currency": [ + "GBP" + ], + "balances": [ + { + "name": "Gen Seg Acc Wsale - TradingBankEnd2End", + "amount": 2000000.00, + "currency": "GBP", + "status": "VALU" + } + ], + "iban": "GB90CLRB04190000001107", + "bban": "CLRB04190000001107" + }, + { + "id": "9b3dd95c-92a0-4c22-8314-da97906f4a2b", + "name": "Mandated Minimum Balance Account", + "type": "CACC", + "currency": [ + "GBP" + ], + "balances": [ + { + "name": "Mandated Minimum Balance Account", + "amount": 2000000.00, + "currency": "GBP", + "status": "VALU" + } + ], + "iban": "GB57CLRB04190000001119", + "bban": "CLRB04190000001119" + }, + { + "id": "0392ffce-fd15-47a6-824f-708e0bee007b", + "name": "Operating Account", + "type": "CACC", + "currency": [ + "GBP" + ], + "balances": [ + { + "name": "Operating Account", + "amount": 1999992.00, + "currency": "GBP", + "status": "VALU" + } + ], + "iban": "GB95CLRB04190000001114", + "bban": "CLRB04190000001114" + } + ], + "halLinks": [ + { + "name": "self", + "href": "https://institution-sim.clearbank.co.uk/v1/Accounts", + "templated": false + }, + { + "name": "Account", + "href": "https://institution-sim.clearbank.co.uk/v1/Accounts/{accountId}", + "templated": true + }, + { + "name": "Transactions", + "href": "https://blue-institution-sim.clearbank.co.uk/v1/Accounts/{accountId}/Transactions", + "templated": true + }, + { + "name": "Mandates", + "href": "https://blue-institution-sim.clearbank.co.uk/v1/Accounts/{accountId}/Mandates", + "templated": true + } + ] +} +``` + +## Subscribe to webhooks + +### Overview + +In response to some events, we generate and send out a webhook message to your defined URL. + +> All ClearBank webhooks consist of a `DigitalSignature`, `Type`,`Version`,`Payload` and `Nonce`. `Payload` parameters vary depending on the webhook. +Webhook responses contain a 200 HTTP status code which includes a `Nonce` number in the body and your `DigitalSignature`. + +### Anatomy of a webhook + +| Element | Type | Description | +| ---------------- | ------------- | -------------------------------------------------------------------------------------------------------- | +| `DigitalSignature` | string | ClearBank®'s Digital Signature | +| `Type` | string | The type of the event | +| `Version` | int | The webhook version | +| `Nonce` | int | Cryptographically secure number generated by ClearBank® for every single webhook. A nonce number is generated randomly and should not be used as a check for duplication | +| `Payload` | array[object] | Object which contains information related to the webhook | + +### Response + +| Element | Type | Description | +| ---------------- | ------------- | --------------------------------------------------------------------------- | +| `DigitalSignature` | string | Signed hash of the body of the request. The hash signed by your private key | +| `Nonce` | int | The value that you receive in the webhook | +| `200 ` | int | HTTP response status code | + +### Responding to a webhook + +The webhook sent by ClearBank® acts as a verification mechanism. +You verify that it is ClearBank® that has sent you the webhook and subsequently, ClearBank® needs to verify that you have successfully received the webhook (based on your response acknowledging receipt). +This verification occurs when you return a `200` HTTP response, which includes the `Nonce` number in the `response body` and your `DigitalSignature`. +If your response is invalid, we will consider it as a failed webhook. +ClearBank® will send the webhook every 15 minutes for 24 hours unless a successful response is returned by you. + +To verify the integrity of the webhook received from ClearBank®: +- Download a Public Key that is specific to your institution by clicking the **Download Public Key** button on the Webhook Management page of the Institution portal. +- Hash the request body using `SHA 256` +- Convert the `DigitalSignature` Request Header value from `Base64` encoded string into the byte array +- Verify the signature using the `RSA` algorithm + +To create the webhook digital signature: +- Take the Nonce number from the webhook and place it in the body of the response (e.g. `{"nonce": }`) +- Hash the response body using `SHA 256` +- Sign the hash with your `Private Key` and attach the signed hash as `Base64` encoded in the `DigitalSignature` Response Header + +> Your Private Key needs to correspond to a Public Key which has been used to create a Certificate Signing Request (CSR). Please refer to [creating your authentication profile](/#creating-your-authentication-profile) for more information. + +Example HTTP request: +``` +POST http://yourdomain.com/sample/webhook HTTP/1.1 +Content-Type: application/json +Content-Length: 72 +Digitalsignature: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY +X-Request-Id: f0309d95-4f68-4ecd-9c8d-b2d08d9fedd8 + +{"Type":"FITestEvent","Version":1,"Payload":"test me","Nonce":1448545215} +``` + +Example HTTP response: +``` +HTTP/1.1 200 OK +Digitalsignature: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +Content-Type: application/json + +{ + "Nonce": 1448545215 +} +``` + +### Setting up and testing webhook listener URLs + +You can create one webhook listener for all events or separate webhook listeners specific to an event. +In this example, you will setup an `FITestEvent` webhook URL, which you can test against the [`TEST POST` endpoint](#test-endpoints). + +To manage your webhook definitions and set your webhook listener URLs for each event: +- Log in to the Institution Portal. More information about accessing the portal can be found [here](/#what-you-need-to-get-started). +- From the menu, select **Institution** > **Webhook Management**. +![alt text](/assets/images/webhook-management-page.png "webhook Management page") +- Search for **Test webhook** and click the **Edit button**. +- Enter the **URL** you want to define as your webhook listener for this webhook and set the webhook status to **Enabled**. +- Click Save to successfully setup the webhook listern URL. +- To test the webhook, click the **Test button**. +- Enter a test message in the Test webhook window for example, ‘Hello World’ and click **Send**. + +You should receive a `FITestEvent webhook` to your nominated URL and it should contain the test message in the body. + +**You must not include any sensitive information (such as API keys) in your webhook URLs.** + +The range of public IP addresses to support your interaction with ClearBank® webhooks are: +- Simulation Public IP address range: `51.145.122.16/28` +- Production Public IP address range: `51.145.122.32/28` diff --git a/content-new/docs/api/overview.mdx b/content-new/docs/api/overview.mdx new file mode 100644 index 000000000..4ac633b43 --- /dev/null +++ b/content-new/docs/api/overview.mdx @@ -0,0 +1,8 @@ +--- +title: "Overview" +order: 1 +--- + +## Overview + +For GET requests, you can use one or more query parameters. In the response we will return a HTTP status code. Some endpoints return JSON bodies that include HAL (Hypertext Application Language) links. diff --git a/content-new/docs/api/parameters.json b/content-new/docs/api/parameters.json new file mode 100644 index 000000000..91872d70c --- /dev/null +++ b/content-new/docs/api/parameters.json @@ -0,0 +1,38 @@ +{ + "authorization": { + "name": "Authorization", + "type": "string", + "location": "header", + "required": true, + "methods": ["get", "post", "patch", "delete", "request"], + "body": "

Your API token retrieved from the portal.

", + "example": "curl -v -X GET https://institution-api-sim.clearbank.co.uk/v3/Accounts \\ \n -H \"Authorization: Bearer <> \"" + }, + "digitalSignature": { + "name": "DigitalSignature", + "type": "string", + "location": "header", + "required": true, + "methods": ["post", "patch", "delete", "request"], + "body": "

This is a hash of the request body signed with your private key.

", + "example": null + }, + "xRequestId": { + "name": "X-Request-Id", + "type": "string", + "location": "header", + "required": true, + "methods": ["post", "patch", "delete", "request"], + "body": "

This is what we use for idempotency and enables a duplication check. You generate this identifier which must be unique for any subsequent requests sent for at least 24 hours after the initial request was sent.

If an X-Request-Id Header is not supplied, or is invalid, a 400:Bad Request HTTP status code response will be returned.

If ClearBank® detects a duplicate, a 409: Conflict HTTP status code response will be returned.

", + "example": null + }, + "xCorrelationId": { + "name": "X-Correlation-Id", + "type": "string", + "location": "header", + "required": false, + "methods": ["response"], + "body": "

This is a unique identifier generated by ClearBank® for the request. ClearBank® would require this identifier for troubleshooting purposes. Therefore, it is recommended you store this response header.

", + "example": null + } +} diff --git a/content-new/docs/api/parameters.ts b/content-new/docs/api/parameters.ts new file mode 100644 index 000000000..7347e7117 --- /dev/null +++ b/content-new/docs/api/parameters.ts @@ -0,0 +1,9 @@ +export interface Parameter { + name: string + type: string + location: string + required: boolean + methods: string[] + body: string + example?: string +} diff --git a/content-new/docs/api/support-lify-cycle.mdx b/content-new/docs/api/support-lify-cycle.mdx new file mode 100644 index 000000000..7d9236146 --- /dev/null +++ b/content-new/docs/api/support-lify-cycle.mdx @@ -0,0 +1,24 @@ +--- +title: "Support life cycle" +order: 4 +--- + +import Callout from "src/components/callout"; + +## Support life cycle + +All endpoints and webhooks released by ClearBank will be supported for a minimum of 12 months before these are reviewed for withdrawal. + +Following the initial 12-month period, all endpoints and webhooks will be reviewed every 6 months. This review will allow us to decide whether an endpoint or webhook should be withdrawn. +If we decide to withdraw an endpoint or webhook, you will be issued a written notification 6 months prior to the date from which that version will no longer be supported. + +This means that all endpoints and webhooks will ideally be supported for a minimum of 18 months (this includes initial support for 12 months along with a 6-month advance notice period prior to withdrawal). + +The only exception to this approach would be for us to withdraw an endpoint or webhook sooner due to regulatory or scheme obligations, or in case of API incompatibility. + +As a matter of practice, you are urged to ensure that you upgrade to the latest version of an endpoint or webhook as soon as one is released. + + + Any changes to our API versioning approach will be communicated to you at + least 6 months prior to implementation. + diff --git a/content-new/docs/api/versioning.mdx b/content-new/docs/api/versioning.mdx new file mode 100644 index 000000000..a10c04d50 --- /dev/null +++ b/content-new/docs/api/versioning.mdx @@ -0,0 +1,17 @@ +--- +title: "Versioning" +order: 3 +--- + +## Versioning + +Providing developers with a seamless integration experience is at the core of our API versioning approach. We work in an agile environment and iteratively release the latest versions of individual endpoints and webhooks. + +We follow the Semantic Versioning specification (https://semver.org/): + +- Internally, we update minor and patch versions whenever we add optional functionality and backwards compatible changes. +- Whenever we introduce a breaking change, we will provision a new major version of the API. + +All API endpoints are versioned through the URI path; for example, /v2/Accounts. Endpoint details can be found on the Developer Portal. + +A backwards compatible change does not affect existing integrations for tolerant readers, for example the addition of new optional fields for an API request, response or a webhook payload. A breaking change could affect existing integrations, for example the addition of a new mandatory field or removal of an existing field. diff --git a/content-new/docs/embedded-banking.mdx b/content-new/docs/embedded-banking.mdx new file mode 100644 index 000000000..0b00f4fd4 --- /dev/null +++ b/content-new/docs/embedded-banking.mdx @@ -0,0 +1,7 @@ +--- +title: "Embedded Banking" +order: 5 +metaTitle: "Embedded Banking" +metaDescription: "" +showPageMenu: true +--- \ No newline at end of file diff --git a/content-new/docs/embedded-banking/fscs-protected-deposits.mdx b/content-new/docs/embedded-banking/fscs-protected-deposits.mdx new file mode 100644 index 000000000..0a22e75dc --- /dev/null +++ b/content-new/docs/embedded-banking/fscs-protected-deposits.mdx @@ -0,0 +1,59 @@ +--- +title: "FSCS protected deposites" +order: 1 +--- + +import EndpointBlock from "src/components/endpoint-block"; +import * as CONSTANTS from "./retail-customers.constants" + +## FSCS protected deposites + +FSCS-protected deposits are a part of our embedded banking proposition. An FSCS-protected deposit is a physical account held with ClearBank and is only available to our embedded banking customers for the purpose of sending and/or receiving payments. The balance of an FSCS-protected deposit is held by ClearBank and can be viewed via the ClearBank Portal and the API. Additionally, FSCS-protected deposits are reconciled for you by ClearBank. + + + + + + + + diff --git a/content-new/docs/embedded-banking/retail-customers.constants.tsx b/content-new/docs/embedded-banking/retail-customers.constants.tsx new file mode 100644 index 000000000..0feb25f2c --- /dev/null +++ b/content-new/docs/embedded-banking/retail-customers.constants.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export const postCustomersRetailDescription = ( + <> +

+ Once you have created a retail customer, create a new FSCS protected current account using the retail customer’s unique Id. +

+ +); diff --git a/content-new/docs/gbp-accounts.mdx b/content-new/docs/gbp-accounts.mdx new file mode 100644 index 000000000..04a75a16b --- /dev/null +++ b/content-new/docs/gbp-accounts.mdx @@ -0,0 +1,7 @@ +--- +title: "GBP Accounts" +order: 2 +metaTitle: "GBP Accounts" +metaDescription: "" +showPageMenu: true +--- \ No newline at end of file diff --git a/content-new/docs/gbp-accounts/account-types.mdx b/content-new/docs/gbp-accounts/account-types.mdx new file mode 100644 index 000000000..f3bcd2862 --- /dev/null +++ b/content-new/docs/gbp-accounts/account-types.mdx @@ -0,0 +1,31 @@ +--- +title: "Account types" +order: 1 +--- + +import Callout from "src/components/callout"; + +## Overview + +There are several types of accounts that can be created. Which you should use will depend on your agreement with ClearBank, and the purpose of the account. + +When you join ClearBank you are given these five accounts by default: + +![Image showing your initial set of accounts](/assets/images/Accounts-Day1.svg "Initial set of accounts") + +Your **institution account** is not an account of its own; it is a superset of all your other accounts. Your **operating account** holds your own operational funds and your **general segregation account** can be used for multiple customers' funds that need to be safeguarded. Note that a segregation account should not be used to hold any of your own funds. + +You can create additional operational and safeguarding accounts as needed. You can also create virtual accounts within a general segregation account or a general client account. + +![Image showing correct usage of usageType/kind](/assets/images/Accounts-Usage.svg "Correct usage of usageType/kind") + +It is important to **select the correct usage for the account when you create it, as this cannot be amended later**. The account usage determines, for example, whether the account can be used for safeguarding funds. + +When you create a real account: +- For sterling accounts - use the **UsageType** field to select YourFunds, SegregatedDesignated, or SegregatedGeneral, as shown above. If you need to create a client account, first create a safeguarding account through the API, then contact client services through FreshDesk to have the type transferred to a client account. + +- For multi-currency accounts - use the **Kind** field to select YourFunds, DesignatedSegregated, GeneralSegregated, DesignatedClient, or GeneralClient. + +The UsageType or Kind value determines the autogenerated prefix assigned to the account, for example, 'Gen Seg Acc Retl'. The prefixes for each account are shown in the figure above. + +The endpoints described below are used to manage sterling accounts. For multi-currency accounts, see [Multi-currency Accounts](./multicurrency-accounts). diff --git a/content-new/docs/gbp-accounts/bacs-payment-data.mdx b/content-new/docs/gbp-accounts/bacs-payment-data.mdx new file mode 100644 index 000000000..482dbccf4 --- /dev/null +++ b/content-new/docs/gbp-accounts/bacs-payment-data.mdx @@ -0,0 +1,4 @@ +--- +title: "BACS Payment data" +order: 4 +--- diff --git a/content-new/docs/gbp-accounts/manage-accounts.mdx b/content-new/docs/gbp-accounts/manage-accounts.mdx new file mode 100644 index 000000000..26629dcd7 --- /dev/null +++ b/content-new/docs/gbp-accounts/manage-accounts.mdx @@ -0,0 +1,174 @@ +--- +title: "Manage accounts" +order: 2 +--- + +import EndpointBlock from "src/components/endpoint-block"; +import * as ACCOUNTS_CONSTANTS from "./real-accounts.constants" +import * as VIRTUAL_ACC_CONSTANTS from "./virtual-accounts.constants" + +import WebhookPlaceholder from 'src/components/webhook-placeholder' +import WebhookSummary from 'src/components/webhook-summary' + +## Real GBP accounts + +A real account is a physical account held with ClearBank and can be used to send and/or receive payments. +The balance of a real account is also held by ClearBank and can be viewed via the Institution portal and the ClearBank API. Real accounts are reconciled for you by ClearBank. + + + + + + + + + + + + + +## Virtual GBP accounts + +A virtual account held with ClearBank is a shadow account which should mirror an account held on your platform. +Each virtual account is linked to a real account held at ClearBank. You can use a virtual account to send and/or receive payments by means of its association with this real account. +The responsibility of managing and reconciling virtual accounts rests with you, which gives you complete control of such accounts. + + + + + + + + + + + + + + + + + + diff --git a/content-new/docs/gbp-accounts/payment-data.mdx b/content-new/docs/gbp-accounts/payment-data.mdx new file mode 100644 index 000000000..9546fc0e2 --- /dev/null +++ b/content-new/docs/gbp-accounts/payment-data.mdx @@ -0,0 +1,4 @@ +--- +title: "Payment data" +order: 3 +--- diff --git a/content-new/docs/gbp-accounts/real-accounts.constants.tsx b/content-new/docs/gbp-accounts/real-accounts.constants.tsx new file mode 100644 index 000000000..f351209a5 --- /dev/null +++ b/content-new/docs/gbp-accounts/real-accounts.constants.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export const postAccountsDescription = ( + <> +

+ This endpoint uses the X-Request-Id as a duplicate check and to ensure the request is idempotent. +

+ +); diff --git a/content-new/docs/gbp-accounts/virtual-accounts.constants.tsx b/content-new/docs/gbp-accounts/virtual-accounts.constants.tsx new file mode 100644 index 000000000..73505de85 --- /dev/null +++ b/content-new/docs/gbp-accounts/virtual-accounts.constants.tsx @@ -0,0 +1,10 @@ +import React from "react"; + +export const postVirtualAccountsDescription = ( + <> +

+ This endpoint uses accountIdentifier as a duplicate check and to ensure the request is idempotent. +

+ +); + diff --git a/content-new/docs/index.mdx b/content-new/docs/index.mdx new file mode 100644 index 000000000..79b630b5b --- /dev/null +++ b/content-new/docs/index.mdx @@ -0,0 +1,6 @@ +--- +title: "Home" +order: -1 +metaTitle: "This is the title tag of this page" +metaDescription: "" +--- diff --git a/content-new/docs/multi-currency.mdx b/content-new/docs/multi-currency.mdx new file mode 100644 index 000000000..2badefcaa --- /dev/null +++ b/content-new/docs/multi-currency.mdx @@ -0,0 +1,7 @@ +--- +title: "Multi-currency" +order: 4 +metaTitle: "Multi-currency" +metaDescription: "" +showPageMenu: true +--- \ No newline at end of file diff --git a/content-new/docs/multi-currency/account-reporting.mdx b/content-new/docs/multi-currency/account-reporting.mdx new file mode 100644 index 000000000..4856320cb --- /dev/null +++ b/content-new/docs/multi-currency/account-reporting.mdx @@ -0,0 +1,4 @@ +--- +title: "Account reporting" +order: 3 +--- diff --git a/content-new/docs/multi-currency/fx-trade.mdx b/content-new/docs/multi-currency/fx-trade.mdx new file mode 100644 index 000000000..b7586c36e --- /dev/null +++ b/content-new/docs/multi-currency/fx-trade.mdx @@ -0,0 +1,4 @@ +--- +title: "FX Trade" +order: 5 +--- diff --git a/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx b/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx new file mode 100644 index 000000000..1462900a5 --- /dev/null +++ b/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx @@ -0,0 +1,4 @@ +--- +title: "Manage multi-currency accounts" +order: 2 +--- diff --git a/content-new/docs/multi-currency/multi-currency-account-types.mdx b/content-new/docs/multi-currency/multi-currency-account-types.mdx new file mode 100644 index 000000000..b6444f958 --- /dev/null +++ b/content-new/docs/multi-currency/multi-currency-account-types.mdx @@ -0,0 +1,4 @@ +--- +title: "Multi-currency account types" +order: 1 +--- diff --git a/content-new/docs/multi-currency/multi-currency-payments.mdx b/content-new/docs/multi-currency/multi-currency-payments.mdx new file mode 100644 index 000000000..eb04765b5 --- /dev/null +++ b/content-new/docs/multi-currency/multi-currency-payments.mdx @@ -0,0 +1,4 @@ +--- +title: "Multi-currency payments" +order: 4 +--- diff --git a/content-new/docs/uk-payments.mdx b/content-new/docs/uk-payments.mdx new file mode 100644 index 000000000..ce6c782df --- /dev/null +++ b/content-new/docs/uk-payments.mdx @@ -0,0 +1,7 @@ +--- +title: "UK Payments" +order: 3 +metaTitle: "UK Payments" +metaDescription: "" +showPageMenu: true +--- \ No newline at end of file diff --git a/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx b/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx new file mode 100644 index 000000000..1a4ed4574 --- /dev/null +++ b/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx @@ -0,0 +1,4 @@ +--- +title: "Bacs Direct Debit Instructions" +order: 4 +--- diff --git a/content-new/docs/uk-payments/bacs.mdx b/content-new/docs/uk-payments/bacs.mdx new file mode 100644 index 000000000..28653714b --- /dev/null +++ b/content-new/docs/uk-payments/bacs.mdx @@ -0,0 +1,4 @@ +--- +title: "Bacs" +order: 3 +--- diff --git a/content-new/docs/uk-payments/chaps.mdx b/content-new/docs/uk-payments/chaps.mdx new file mode 100644 index 000000000..64d0a24fe --- /dev/null +++ b/content-new/docs/uk-payments/chaps.mdx @@ -0,0 +1,4 @@ +--- +title: "CHAPS" +order: 5 +--- diff --git a/content-new/docs/uk-payments/confirmation-of-payee.mdx b/content-new/docs/uk-payments/confirmation-of-payee.mdx new file mode 100644 index 000000000..67c76cb10 --- /dev/null +++ b/content-new/docs/uk-payments/confirmation-of-payee.mdx @@ -0,0 +1,4 @@ +--- +title: "Confirmation Of Payee (CoP)" +order: 6 +--- diff --git a/content-new/docs/uk-payments/faster-payments.mdx b/content-new/docs/uk-payments/faster-payments.mdx new file mode 100644 index 000000000..251f03493 --- /dev/null +++ b/content-new/docs/uk-payments/faster-payments.mdx @@ -0,0 +1,4 @@ +--- +title: "Faster payments" +order: 2 +--- diff --git a/content-new/docs/uk-payments/internal-transfers.mdx b/content-new/docs/uk-payments/internal-transfers.mdx new file mode 100644 index 000000000..db1237360 --- /dev/null +++ b/content-new/docs/uk-payments/internal-transfers.mdx @@ -0,0 +1,4 @@ +--- +title: "Internal transfers" +order: 1 +--- diff --git a/gatsby-config.js b/gatsby-config.js index 978ca8a42..41f539c58 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -25,7 +25,7 @@ const plugins = [ resolve: 'gatsby-source-filesystem', options: { name: 'docs', - path: `${__dirname}/content/` + path: `${__dirname}/content-new/` } }, { @@ -114,6 +114,6 @@ module.exports = { headerLinks: config.header.links, siteUrl: config.gatsby.siteUrl }, - trailingSlash: 'always', + trailingSlash: 'never', plugins: plugins } diff --git a/package-lock.json b/package-lock.json index 07ae8cff3..09129a2a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "@types/react-transition-group": "^4.2.4", "@types/rebass": "^4.0.4", "@types/styled-components": "^5.1.0", + "classnames": "^2.3.2", "dotenv": "^8.2.0", "element-react": "^1.4.34", "element-theme-chalk": "^2.13.0", diff --git a/package.json b/package.json index c9857ffef..c9f8d8e2c 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@types/react-transition-group": "^4.2.4", "@types/rebass": "^4.0.4", "@types/styled-components": "^5.1.0", + "classnames": "^2.3.2", "dotenv": "^8.2.0", "element-react": "^1.4.34", "element-theme-chalk": "^2.13.0", diff --git a/src/components/header-menu/header-menu.styles.ts b/src/components/header-menu/header-menu.styles.ts new file mode 100644 index 000000000..73fabf288 --- /dev/null +++ b/src/components/header-menu/header-menu.styles.ts @@ -0,0 +1,77 @@ +import styled, { css } from 'styled-components' +import { colors } from 'src/components/theme' +import { Link } from 'gatsby' + +export const LinkBase = styled(Link)` + padding: 0; + display: block; + border-color: transparent; + transition: none; + outline: none; + background-color: transparent; + cursor: pointer; + text-decoration: none; +` + +export const MenuContainer = styled.div` + display: flex; + justify-content: space-between; + margin: 0px 75px; +` + +export const Container = styled.div` + padding: 25px 0px; + position: relative; + min-width: 120px; + + &:hover { + color: ${colors.wedgewoodapprox}; + } +` + +export const TitleContainer = styled.div` + padding: 0px 13px; +` + +export const Underline = styled.div` + background: #8E8E8E; + margin-top: 7px; + height: 3px; + width: 100%; + border-radius: 10px; +` + +export const Title = styled(LinkBase)` + line-height: 38px; + font-size: 25px; + font-weight: ${props => props.isActive ? 500 : 400}; + color: ${props => props.isActive ? colors.wedgewoodapprox : colors.brandDark}; + + &:hover { + color: ${colors.wedgewoodapprox}; + } +` + +export const List = styled.ul` + display: none; + z-index: 1; + width: 100%; + margin-top: 15px; + position: absolute; + background: ${colors.brandGrayLight}; + border-radius: 0px 0px 10px 10px; + list-style: none; + + ${Container}:hover & { + display: block; + } +` + +export const ListItem = styled(LinkBase)` + padding: 15px; + color: ${colors.brandDark}; + + &:hover { + color: ${colors.wedgewoodapprox}; + } +` \ No newline at end of file diff --git a/src/components/header-menu/header-menu.tsx b/src/components/header-menu/header-menu.tsx new file mode 100644 index 000000000..cb2487bab --- /dev/null +++ b/src/components/header-menu/header-menu.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +import { hasWindow } from 'src/utils/browser.services' +import HeaderSubMenu from './header-sub-menu' +import * as Styles from './header-menu.styles' + +const isMenuActive = (item) => { + const currentPath = hasWindow() ? window.location.pathname : '' + + return currentPath === item.menuItem.slug +} + +const HeaderMenu = ({ items, currentPathname }) => { + + return ( + + {items.map(item => )} + + ) +} + + export default HeaderMenu \ No newline at end of file diff --git a/src/components/header-menu/header-sub-menu.tsx b/src/components/header-menu/header-sub-menu.tsx new file mode 100644 index 000000000..3f1e22a17 --- /dev/null +++ b/src/components/header-menu/header-sub-menu.tsx @@ -0,0 +1,44 @@ +import React from 'react' +import classnames from 'classnames' + +import * as Styles from './header-menu.styles' + +const HeaderSubMenu = ({ item, isActive }) => { + return ( + + + + {item.menuItem.title} + + { + isActive && ( + + ) + } + + + {item.subMenuItems?.map(subMenuItem => { + const [hash] = subMenuItem.node.fields.slug.match(new RegExp(/[^\/]+$/)) + const link = `${item.menuItem.slug}#${hash}` + + return ( +
  • + {subMenuItem.node.fields.title} +
  • + ) + })} +
    +
    + ) + } + + export default HeaderSubMenu \ No newline at end of file diff --git a/src/components/header-menu/index.ts b/src/components/header-menu/index.ts new file mode 100644 index 000000000..411dbe5ff --- /dev/null +++ b/src/components/header-menu/index.ts @@ -0,0 +1 @@ +export { default } from './header-menu' \ No newline at end of file diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx index 24435b72f..a91fe9b49 100644 --- a/src/components/header/header.tsx +++ b/src/components/header/header.tsx @@ -28,7 +28,7 @@ const Header: React.FunctionComponent = ({ menuItems, current
    - + diff --git a/src/components/layout/layout.styles.ts b/src/components/layout/layout.styles.ts index abf3aa278..816f4c89f 100644 --- a/src/components/layout/layout.styles.ts +++ b/src/components/layout/layout.styles.ts @@ -32,9 +32,9 @@ export const Wrapper = styled.div` @media screen and (min-width: ${breakpoints.large}) { grid-template-areas: - 'header header header' - 'sidebarLeft content sidebarRight' - 'sidebarLeft footer footer'; + 'header header header' + 'content content sidebarRight' + 'footer footer footer'; grid-template-rows: ${heights.header} 1fr @@ -61,7 +61,7 @@ export const HeaderWrapper = styled.header` position: fixed; left: 0; right: 0; - background: ${colors.downriver}; + background: ${colors.brandLight}; z-index: 1; ` diff --git a/src/components/layout/layout.tsx b/src/components/layout/layout.tsx index cc69aaac9..28052de2a 100644 --- a/src/components/layout/layout.tsx +++ b/src/components/layout/layout.tsx @@ -10,6 +10,7 @@ import Sidebar from 'src/components/sidebar' import PageMenu from 'src/components/pageMenu' import Pagination from 'src/components/pagination' import BackToTop from 'src/components/back-to-top' +import HeaderMenu from 'src/components/header-menu' import * as Styles from './layout.styles' import * as Types from './layout.types' @@ -39,12 +40,10 @@ const Layout: React.FunctionComponent = ({ menuItems={pageContext.menuItems} currentPageURL={`${pathname}${hash}`} /> + - + {/* <> - {/* I'm not sure why we have to do a check here for pageContext.menuItems && */} - {/* But not having it breaks the build (not development) */} - {/* I think it must do two runs and doesn't have it the first time around */} {!!menuItems && ( = ({ /> )} - + */} {children} diff --git a/src/components/theme.ts b/src/components/theme.ts index 4a57f4593..fc4973797 100644 --- a/src/components/theme.ts +++ b/src/components/theme.ts @@ -77,7 +77,7 @@ export const widths: Types.Widths = { } export const heights: Types.Heights = { - header: '60px' + header: '160px' } export const maxWidths: Types.MaxWidths = { @@ -183,6 +183,7 @@ export const colors = { blackSqueeze: '#f3fbfb', // V2 concrete: '#F2F2F2', // V2 alto: '#E0E0E0', // V2 + wedgewoodapprox: '#478E96', // New branding colours V2 - TODO: these color vars need sorting out billionaireBlue: '#000000', From e9b7ccbdd9b9485e9b8cbae30e8ed5f5f38eef72 Mon Sep 17 00:00:00 2001 From: Anton Adamkovich Date: Mon, 27 Mar 2023 02:52:49 -0700 Subject: [PATCH 2/9] add header menu types --- .../docs/multi-currency/account-reporting.mdx | 73 +++ content-new/docs/multi-currency/fx-trade.mdx | 91 +++ .../manage-multi-currency-accounts.mdx | 192 ++++++ .../multi-currency-account-types.mdx | 27 + .../multi-currency-payments.mdx | 591 ++++++++++++++++++ .../bacs-direct-debit-instructions.mdx | 159 +++++ content-new/docs/uk-payments/chaps.mdx | 48 ++ .../confirmation-of-payee.constants.tsx | 17 + .../uk-payments/confirmation-of-payee.mdx | 95 +++ .../docs/uk-payments/faster-payments.mdx | 89 +++ .../docs/uk-payments/internal-transfers.mdx | 17 + ...ng-direct-debit-instructions.constants.tsx | 17 + src/components/header-menu/header-menu.tsx | 7 +- .../header-menu/header-meny.types.ts | 26 + .../header-menu/header-sub-menu.tsx | 11 +- src/components/header/header.styles.ts | 2 +- src/components/layout/layout.tsx | 11 - src/components/theme.ts | 2 +- 18 files changed, 1454 insertions(+), 21 deletions(-) create mode 100644 content-new/docs/uk-payments/confirmation-of-payee.constants.tsx create mode 100644 content-new/docs/uk-payments/managing-direct-debit-instructions.constants.tsx create mode 100644 src/components/header-menu/header-meny.types.ts diff --git a/content-new/docs/multi-currency/account-reporting.mdx b/content-new/docs/multi-currency/account-reporting.mdx index 4856320cb..3cc3cc9ca 100644 --- a/content-new/docs/multi-currency/account-reporting.mdx +++ b/content-new/docs/multi-currency/account-reporting.mdx @@ -2,3 +2,76 @@ title: "Account reporting" order: 3 --- + +import EndpointBlock from "src/components/endpoint-block"; + +## Multi-currency transactions + +Multicurrency transaction endpoints allow you to retrieve a list of transactions for a multicurrency account and any virtual accounts associated with it, a multicurrency virtual account as well as a single transaction. + + + + + + + +## Multi-currency statements + +Your multicurrency bank statement is an official summary of financial transactions that have occurred for all multicurrency accounts within a calendar month. + +Statements can either be generated for all accounts associated with your institution or a specific real account associated with your institution. + + + + diff --git a/content-new/docs/multi-currency/fx-trade.mdx b/content-new/docs/multi-currency/fx-trade.mdx index b7586c36e..e228bc888 100644 --- a/content-new/docs/multi-currency/fx-trade.mdx +++ b/content-new/docs/multi-currency/fx-trade.mdx @@ -2,3 +2,94 @@ title: "FX Trade" order: 5 --- + +import EndpointBlock from "src/components/endpoint-block"; +import WebhookPlaceholder from 'src/components/webhook-placeholder' +import WebhookSummary from 'src/components/webhook-summary' + +## Overview + +Our FX Trade offering allows you to buy and sell currency in real-time – you submit a trade order to ClearBank, we perform the required validation checks on your order and upon successful validation, execute it in the foreign exchange market against live market rates. + +You can use our FX trade functionality to perform FX trades between accounts which belong to the same owner. For example, let’s assume that you want to sell GBP from Account A to purchase EUR for Account B – in doing so, you will need to ensure that the owner of both accounts is the same. This applies to two accounts that belong to you i.e., the financial institution or your customers. + +When initiating a FX trade order via our API, you can either specify the amount of the currency you wish to buy or the amount you wish to sell. The specified amount (and currency) is referred to as the fixed side of the trade. Whereas the amount (and currency) that has not been specified is referred to as the floating side of the trade. + +Additionally, you can also specify your margin (%) to be applied to the trade. The margin amount is automatically calculated, applied to the credit/debit transaction amount of the buy and sell accounts, and credited to a separate account of your choice. The margin is always reflected in the calculation of the credit/debit transaction of the floating currency. + +### Example: Specifying the sell amount with margin + +**Trade Request:** + +- InstructedAmount: 1000 +- FixedSide: Sell +- BuyCurrency: USD +- SellCurrency: GBP (This means the fixed side of the trade is GBP and the floating side is USD. Therefore, the margin will be in USD). +- Margin: 0.01 (Where 0.01 represents a 1% margin) +- Assume the ClearBank rate is: 1.40 for GBP/USD +- Margin amount: 1.4 x 0.01 x GBP 1000 = USD 14 + +**Resulting transactions in respective accounts:** + +- Debit to the sellAccount: GBP 1000.00 +- Credit to the buyAccount: USD 1386 [USD 1.4 x (1-0.01) x 1000] +- Credit to the specified margin account: USD 14 + +### Example: Specifying the buy amount with margin + +**Trade Request:** + +- InstructedAmount: 1400 +- FixedSide: Buy +- BuyCurrency: USD +- SellCurrency: GBP +- This means the fixed side of the trade is USD and the floating side is GBP, therefore the margin will be in GBP +- Margin: 0.01 (Where 0.01 represents a 1% margin) +- Assume the ClearBank rate is: 1.40 for GBP/USD +- Margin amount: 1400 / 1.4 x 0.01 = GBP 10 + +**Resulting transactions in respective accounts:** + +- Debit to the sellAccount: GBP [1110 (1400 / 1.4 x (1 + 0.01)] +- Credit to the buyAccount: USD 1400 +- Credit to the specified margin account: GBP 10 + +#### FX trades are subject to cut-off times: + * If a trade is booked in time for same-day settlement, you will receive a webhook notification of the settlement. If it fails to settle (in practice, because there are insufficient funds in the account), you will learn of the failure immediately. ClearBank will then send a [fx-trade-cancelled-v1](../webhooks/#fx-trade-cancelled-webhook) webhook. + * If a trade is booked, but cannot be settled until a later day, and the settlement fails, the [fx-trade-settlement-failed-v1](../webhooks/#fx-trade-settlement-failed-webhook) webhook notifies you of the failure. Make sure you subscribe to this webhook if you are making FX trades with a value (settlement) date later than the day of booking. + + For more information about cut-off times, please speak to your Relationship Manager. + + + + + + + + + diff --git a/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx b/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx index 1462900a5..e8d866764 100644 --- a/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx +++ b/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx @@ -2,3 +2,195 @@ title: "Manage multi-currency accounts" order: 2 --- + +import EndpointBlock from "src/components/endpoint-block"; + +## Real MCCY accounts + +A multi-currency account is a real account held with ClearBank and can be used to send and/or receive payments. The balance of a multi-currency account is also held by ClearBank. + +You can use a multi-currency account to hold multiple non-GBP currency balances under the same IBAN, which can be specified at the time of creating the account via our API. Prior to assigning your desired IBAN to the account, we will validate it to ensure that the IBAN format is acceptable and not already in use. + +At this time, you cannot open or hold GBP balances in a multi-currency account. GBP payments to and from a multi-currency account are not currently allowed either and would be rejected and returned automatically. + +If you already hold a GBP account with ClearBank, your new multi-currency account will be opened under a sort code that is different to the one associated with your existing GBP account. ClearBank will set up the non-GBP currency sort code for you as part of onboarding. + +For more information about currencies supported by ClearBank multi-currency accounts, please speak to your Relationship Manager. + + + + + + + + + + + + + + + + + +## Virtual MCCY account + + +Multi-currency virtual accounts are publicly addressable accounts with their own IBAN. Also known as shadow accounts, multi-currency virtual accounts are linked to real accounts and are used to separate out funds held in real accounts for the purposes of improved reconciliation and liquidity management. Additionally, the responsibility of managing and reconciling virtual accounts rests with you, giving you complete control of such accounts. + +Multi-currency virtual accounts are only compatible with General Client Accounts and General Segregated Accounts, and can be created, suspended or activated and closed via the ClearBank API. + +Multi-currency virtual accounts are enabled for balances of the same currencies as their associated real accounts. For example, if a real multi-currency account is enabled for CHF, EUR and USD, all virtual accounts opened under that real account are also automatically enabled for the same currencies. + +To comply with the Funds Transfer Regulation, it is important that the naming of virtual accounts reflects the legal name of the customer. + + + + + + + + + + diff --git a/content-new/docs/multi-currency/multi-currency-account-types.mdx b/content-new/docs/multi-currency/multi-currency-account-types.mdx index b6444f958..cfe61533b 100644 --- a/content-new/docs/multi-currency/multi-currency-account-types.mdx +++ b/content-new/docs/multi-currency/multi-currency-account-types.mdx @@ -2,3 +2,30 @@ title: "Multi-currency account types" order: 1 --- + +import Callout from "src/components/callout"; + +## Multi-currency account types + +There are several types of accounts that can be created. Which you should use will depend on your agreement with ClearBank, and the purpose of the account. + +When you join ClearBank you are given these five accounts by default: + +![Image showing your initial set of accounts](/assets/images/Accounts-Day1.svg "Initial set of accounts") + +Your **institution account** is not an account of its own; it is a superset of all your other accounts. Your **operating account** holds your own operational funds and your **general segregation account** can be used for multiple customers' funds that need to be safeguarded. Note that a segregation account should not be used to hold any of your own funds. + +You can create additional operational and safeguarding accounts as needed. You can also create virtual accounts within a general segregation account or a general client account. + +![Image showing correct usage of usageType/kind](/assets/images/Accounts-Usage.svg "Correct usage of usageType/kind") + +It is important to **select the correct usage for the account when you create it, as this cannot be amended later**. The account usage determines, for example, whether the account can be used for safeguarding funds. + +When you create a real account: +- For sterling accounts - use the **UsageType** field to select YourFunds, SegregatedDesignated, or SegregatedGeneral, as shown above. If you need to create a client account, first create a safeguarding account through the API, then contact client services through FreshDesk to have the type transferred to a client account. + +- For multi-currency accounts - use the **Kind** field to select YourFunds, DesignatedSegregated, GeneralSegregated, DesignatedClient, or GeneralClient. + +The UsageType or Kind value determines the autogenerated prefix assigned to the account, for example, 'Gen Seg Acc Retl'. The prefixes for each account are shown in the figure above. + +The endpoints described below are used to manage sterling accounts. For multi-currency accounts, see [Multi-currency Accounts](./multicurrency-accounts). diff --git a/content-new/docs/multi-currency/multi-currency-payments.mdx b/content-new/docs/multi-currency/multi-currency-payments.mdx index eb04765b5..c88bf7c58 100644 --- a/content-new/docs/multi-currency/multi-currency-payments.mdx +++ b/content-new/docs/multi-currency/multi-currency-payments.mdx @@ -2,3 +2,594 @@ title: "Multi-currency payments" order: 4 --- + +import EndpointBlock from "src/components/endpoint-block"; + +## Internal Transfer (MCCY) + +You can initiate payments between two ClearBank multicurrency accounts that you operate. This process is known as an internal transfer request. For an internal transfer request to be processed successfully, it is imperative that both accounts are enabled for the instructed currency. + + + + +## Multi-currency Internal Transfer Settled Webhook + +#### Request body + +```json +{ + "Type":"Mccy.InternalTransfers.Settled", + "Version": 1, + "Payload": {...}, + "Nonce": +} +``` + +#### Payload +| Element | Description | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `DebitAccountIban` | *Optional*
    International Bank Account Number for the debtor account.
    Type: `string`
    | +| `DebitAccountOther` | *Optional*
    The unique identifier for the specified account if an IBAN is not provided. It is an object with a Kind and an Identifier. Mandatory only if the IBAN is not provided.
    Type: `object`

    `Kind`
    The kind of account identifier provided. This can only be AccountId.
    Type: `string`
    Min. Length: `1`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `CreditAccountIban` | *Optional*
    International Bank Account Number for the creditor account.
    Type: `string`
    | +| `CreditAccountOther` | *Optional*
    The unique identifier for the specified account if an IBAN is not provided. It is an object with a Kind and an Identifier. Mandatory only if the IBAN is not provided.
    Type: `object`

    `Kind`
    The kind of account identifier provided. This can only be AccountId.
    Type: `string`
    Min. Length: `1`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `InstructedAmount` | **Required**
    Instructed internal transfer amount.
    Type: `number`
    Format: `decimal`
    | +| `InstructedCurrency` | **Required**
    Currency of the instructed internal transfer. This is the 3-letter ISO currency code.
    Type: `string`
    Min. Length: `3`
    Max. Length: `3`
    Pattern: `^[A-z]{3}$`
    | +| `EndToEndId` | **Required**
    Unique identifier provided to ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `35`
    | +| `Reference` | *Optional*
    Reference provided by the debtor for the internal transfer.
    Type: `string`
    Min. Length: `0`
    Max. Length: `140`
    | + +#### Example internal transfer settled webhook request body + +```json +{ + "EndToEndId":"56de3483a56942eb90ccacf59661356f", + "DebitAccountIban":"GB00CUBK11223312345678", + "CreditAccountIban":"GB00CUBK88776687654321", + "InstructedCurrency":"NOK", + "InstructedAmount":13, + "Reference":"f92af28f-0635-4d81-893f-6c32af1d2a17" +}, + "Nonce":748394375 +} +``` + +#### Example webhook response + +```json +{ + "Nonce": 748394375 +} +``` + +## High Value International Payments + +You can now send single or bulk high value payments overseas in currencies other than GBP. To be able to initiate high value international payments, we will need you to first fund your SIM account while integrating with our API in the simulation environment. As part of our fund assessment control framework, you will not be able to initiate high value international payments without doing so. + +ClearBank accepts inbound and outbound Euro payments via the TARGET2 scheme only. Inbound payments which are processed via any other scheme apart from TARGET2 will not be accepted by ClearBank. Non-EUR high value international payments are settled according to cut-off times specific to the currency in which the payment is made. + +For more information about the countries that you can send high value payments to, currencies supported by ClearBank and currency cut-off times, please speak to your Relationship Manager. + +### Post cut-off payments are rescheduled +If a multi-currency payment request is received outside of the payment window for a given currency, you will normally receive a success response (202 – Accepted) including an **isScheduled** Boolean field. This will be set to **true**, indicating that the payment was received out-of-window and will be processed the following business day. If the field is set to **false**, the payment will be processed in the currently open payment window. + +If you would prefer not to have the payment processed the following day, you can cancel the payment by using the cancellation endpoints. The cancellation must be received no later than 1 hour prior to the opening of the next payment window. Note that to be able to cancel a payment, you must have specified a batch ID in the original payment request. + +* Use [DELETE /v1/mccy/payments/{batchId}](#cancel-batch-payments) to cancel a whole batch of payments +* Use [DELETE /v1/mccy/payments/{batchId}/{endToEndId}](#cancel-a-single-payment) to cancel an individual payment + + + + + + + + + +## Multicurrency Transaction Created Webhook + +#### Request body + +```json +{ + "Type":"Payments.Mccy.TransactionCreated", + "Version": 1, + "Payload": {...}, + "Nonce": +} +``` + +#### Payload +| Element | Description | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `TransactionId` | **Required**
    Unique internal identifier defined by ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `BatchId` | **Required**
    Unique identifier for the batch in which the payment was submitted.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `EndToEndId` | **Required**
    Unique identifier provided to ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `35`
    | +| `SchemeEndToEndId` | *Optional*
    Unique identifier created by ClearBank for each payment and passed through the scheme to the creditor.
    Type: `string`
    Min. Length: `0`
    Max. Length: `15`
    | +| `AccountId` | **Required**
    Unique identifier for the account held with ClearBank.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `Reference` | **Required**
    Reference provided by the ultimate debtor for the payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorName` | **Required**
    Name of the ultimate creditor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorAccountIdentifiers` | **Required**
    List of account identifiers used to uniquely identify the ultimate creditor.
    It is an array of objects with `Kind` and an `Identifier`.
    Type: `array`

    `Kind`
    The kind of account identifier which is provided. This can be either IBAN, BBAN, AccountId or Descriptor (another kind of identifier).
    Type: `string`
    Min. Length: `1`
    Max. Length: `10`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `UltimateDebtorName` | **Required**
    Name of the ultimate debtor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateDebtorAccountIdentifiers` | **Required**
    List of account identifiers used to uniquely identify the ultimate debtor.
    It is an array of objects with `Kind` and an `Identifier`.
    Type: `array`

    `Kind`
    The kind of account identifier which is provided. This can be either IBAN, BBAN, AccountId or Descriptor (another kind of identifier).
    Type: `string`
    Min. Length: `1`
    Max. Length: `10`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `InstructedAmount` | **Required**
    Instructed payment amount.
    Type: `number`
    Format: `decimal`
    | +| `InstructedCurrency` | **Required**
    Currency of the instructed payment. This is the 3-letter ISO currency code.
    Type: `string`
    Min. Length: `3`
    Max. Length: `3`
    Pattern: `^[A-z]{3}$`
    | +| `SchemePaymentMethod` | **Required**
    Payment scheme used for submitting the transaction.
    Type: `string`
    Min. Length: `1`
    Max. Length: `50`
    | +| `TimestampCreated` | **Required**
    Date and time transaction was created. Time in UTC.
    Type: `string`
    Min. Length: `1`
    Format: `date-time`
    | +| `Identifiers` | **Required**
    List of identifiers.
    It is an array of objects with a `Scope`, `Name` and `Identifier`.
    Type: `array`

    `Scope`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Name`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Identifier`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `250`
    | +| `AdditionalProperties` | **Required**
    List of additional information.
    It is an array of objects with a `Key` and `Value`.
    Type: `array`

    `Key`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Value`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `250`
    | + +#### Example transaction created webhook request body + +```json +{ + "TransactionId":"fd7f3082-72d4-46b3-8e0e-1f66e4a91e13", + "BatchId":"ab55f54a-26c3-4333-93cd-f917bb51ecad", + "EndToEndId":"08c2c49c9e094df59f342a27cb64395c", + "SchemeEndToEndId":"4026da87bb0f4a5", + "AccountId":"50daac8a-72c3-4ae5-a6e3-e71b6187dbef", + "Reference":"My payment reference 12345", + "UltimateCreditorName":"John Baker", + "UltimateCreditorAccountIdentifiers":[ + { + "Kind":"AccountId", + "Identifier":"fd75710b-4c0a-406d-a962-ef5c98836d3f" + } + ], + "UltimateDebtorName":"Clark Kent", + "UltimateDebtorAccountIdentifiers":[ + { + "Kind":"IBAN", + "Identifier":"GB33BUKB20201555555555" + } + ], + "InstructedAmount":100.55, + "InstructedCurrency":"EUR", + "SchemePaymentMethod":"Partner 1", + "TimestampCreated":"2021-05-22T00:00:00", + "Identifiers":[ + { + "Scope":"MCCYOutboundPayments", + "Name":"SchemeEndToEndId", + "Identifier":"4026da87bb0f4a5" + } + ], + "AdditionalProperties":[ + { + "Key":"DebtorName", + "Value":"Acme Studios" + }, + { + "Key":"DebtorCountry", + "Value":"GB" + } + ] +}, + "Nonce":748352091 +} +``` + +#### Example webhook response + +```json +{ + "Nonce": 748352091 +} +``` + + +## Multicurrency Transaction Settled Webhook + +#### Request body + +```json +{ + "Type":"Payments.Mccy.TransactionSettled", + "Version": 1, + "Payload": {...}, + "Nonce": +} +``` + +#### Payload +| Element | Description | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `TransactionId` | **Required**
    Unique internal identifier defined by ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `BatchId` | **Required**
    Unique identifier for the batch in which the payment was submitted.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `EndToEndId` | **Required**
    Unique identifier provided to ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `35`
    | +| `SchemeEndToEndId` | *Optional*
    Unique identifier created by ClearBank for each payment and passed through the scheme to the creditor.
    Type: `string`
    Min. Length: `0`
    Max. Length: `15`
    | +| `AccountId` | **Required**
    Unique identifier for the account held with ClearBank.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `Reference` | **Required**
    Reference provided by the ultimate debtor for the payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorName` | **Required**
    Name of the ultimate creditor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorAccountIdentifiers` | **Required**
    List of account identifiers used to uniquely identify the ultimate creditor.
    It is an array of objects with `Kind` and an `Identifier`.
    Type: `array`

    `Kind`
    The kind of account identifier which is provided. This can be either IBAN, BBAN, AccountId or Descriptor (another kind of identifier).
    Type: `string`
    Min. Length: `1`
    Max. Length: `10`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `UltimateDebtorName` | **Required**
    Name of the ultimate debtor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateDebtorAccountIdentifiers` | **Required**
    List of account identifiers used to uniquely identify the ultimate debtor.
    It is an array of objects with `Kind` and an `Identifier`.
    Type: `array`

    `Kind`
    The kind of account identifier which is provided. This can be either IBAN, BBAN, AccountId or Descriptor (another kind of identifier).
    Type: `string`
    Min. Length: `1`
    Max. Length: `10`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `InstructedAmount` | **Required**
    Instructed payment amount.
    Type: `number`
    Format: `decimal`
    | +| `InstructedCurrency` | **Required**
    Currency of the instructed payment. This is the 3-letter ISO currency code.
    Type: `string`
    Min. Length: `3`
    Max. Length: `3`
    Pattern: `^[A-z]{3}$`
    | +| `SchemePaymentMethod` | **Required**
    Payment scheme used for submitting the transaction.
    Type: `string`
    Min. Length: `1`
    Max. Length: `50`
    | +| `TimestampCreated` | **Required**
    Date and time transaction was created. Time in UTC.
    Type: `string`
    Min. Length: `1`
    Format: `date-time`
    | +| `Identifiers` | **Required**
    List of identifiers.
    It is an array of objects with a `Scope`, `Name` and `Identifier`.
    Type: `array`

    `Scope`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Name`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Identifier`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `250`
    | +| `AdditionalProperties` | **Required**
    List of additional information.
    It is an array of objects with a `Key` and `Value`.
    Type: `array`

    `Key`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Value`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `250`
    | +| `TimestampSettled` | **Required**
    Date and time the transaction settled.
    Type: `string`
    Min. Length: `1`
    Format: `date-time`
    | +| `TimestampSubmitted` | **Required**
    Date and time transaction was submitted. This should be the same as the date and time of TimestampSettled but will reflect a different time if the transaction settlement is delayed. This time will represent the time the transaction should have settled had it not been delayed.
    Type: `string`
    Min. Length: `1`
    Format: `date-time`
    | + +#### Example transaction settled webhook request body + +```json +{ + "TransactionId": "fd7f3082-72d4-46b3-8e0e-1f66e4a91e13", + "BatchId": "ab55f54a-26c3-4333-93cd-f917bb51ecad", + "EndToEndId": "08c2c49c9e094df59f342a27cb64395c", + "SchemeEndToEndId": "4026da87bb0f4a5", + "AccountId": "50daac8a-72c3-4ae5-a6e3-e71b6187dbef", + "Reference": "My payment reference 12345", + "UltimateCreditorName": "John Baker", + "UltimateCreditorAccountIdentifiers": [ + { + "Kind": "AccountId", + "Identifier": "fd75710b-4c0a-406d-a962-ef5c98836d3f" + } + ], + "UltimateDebtorName": "Clark Kent", + "UltimateDebtorAccountIdentifiers": [ + { + "Kind": "IBAN", + "Identifier": "GB33BUKB20201555555555" + } + ], + "InstructedAmount": 100.55, + "InstructedCurrency": "EUR", + "SchemePaymentMethod": "Partner 1", + "TimestampCreated": "2021-05-22T00:00:00", + "Identifiers": [ + { + "Scope": "MCCYOutboundPayments", + "Name": "SchemeEndToEndId", + "Identifier": "4026da87bb0f4a5" + } + ], + "AdditionalProperties": [ + { + "Key": "DebtorName", + "Value": "Acme Studios" + }, + { + "Key": "DebtorCountry", + "Value": "GB" + } + ], + "TimestampSettled": "2020-09-13T012:22:17.4", + "TimestampSubmitted": "2020-09-13T011:26:15.1" +}, + "Nonce":761164091 +} +``` + +#### Example webhook response + +```json +{ + "Nonce": 761164091 +} +``` + + +## Multicurrency Transaction Cancelled Webhook + +#### Request body + +```json +{ + "Type":"Payments.Mccy.TransactionCancelled", + "Version": 1, + "Payload": {...}, + "Nonce": +} +``` + +#### Payload +| Element | Description | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `TransactionId` | **Required**
    Unique internal identifier defined by ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `BatchId` | **Required**
    Unique identifier for the batch in which the payment was submitted.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `EndToEndId` | **Required**
    Unique identifier provided to ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `35`
    | +| `SchemeEndToEndId` | *Optional*
    Unique identifier created by ClearBank for each payment and passed through the scheme to the creditor.
    Type: `string`
    Min. Length: `0`
    Max. Length: `15`
    | +| `AccountId` | **Required**
    Unique identifier for the account held with ClearBank.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `Reference` | **Required**
    Reference provided by the ultimate debtor for the payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorName` | **Required**
    Name of the ultimate creditor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorAccountIdentifiers` | **Required**
    List of account identifiers used to uniquely identify the ultimate creditor.
    It is an array of objects with `Kind` and an `Identifier`.
    Type: `array`

    `Kind`
    The kind of account identifier which is provided. This can be either IBAN, BBAN, AccountId or Descriptor (another kind of identifier).
    Type: `string`
    Min. Length: `1`
    Max. Length: `10`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `UltimateDebtorName` | **Required**
    Name of the ultimate debtor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateDebtorAccountIdentifiers` | **Required**
    List of account identifiers used to uniquely identify the ultimate debtor.
    It is an array of objects with `Kind` and an `Identifier`.
    Type: `array`

    `Kind`
    The kind of account identifier which is provided. This can be either IBAN, BBAN, AccountId or Descriptor (another kind of identifier).
    Type: `string`
    Min. Length: `1`
    Max. Length: `10`

    `Identifier`
    Unique account identifier value that corresponds to the specified account identifier kind.
    Type: `string`
    Min. Length: `1`
    Max. Length: `36`
    | +| `InstructedAmount` | **Required**
    Instructed payment amount.
    Type: `number`
    Format: `decimal`
    | +| `InstructedCurrency` | **Required**
    Currency of the instructed payment. This is the 3-letter ISO currency code.
    Type: `string`
    Min. Length: `3`
    Max. Length: `3`
    Pattern: `^[A-z]{3}$`
    | +| `SchemePaymentMethod` | **Required**
    Payment scheme used for submitting the transaction.
    Type: `string`
    Min. Length: `1`
    Max. Length: `50`
    | +| `TimestampCreated` | **Required**
    Date and time transaction was created. Time in UTC.
    Type: `string`
    Min. Length: `1`
    Format: `date-time`
    | +| `Identifiers` | **Required**
    List of identifiers.
    It is an array of objects with a `Scope`, `Name` and `Identifier`.
    Type: `array`

    `Scope`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Name`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Identifier`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `250`
    | +| `AdditionalProperties` | **Required**
    List of additional information.
    It is an array of objects with a `Key` and `Value`.
    Type: `array`

    `Key`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `50`

    `Value`
    Type: `string`
    Min. Length: `1`
    Max. Lenght: `250`
    | +| `TimestampCancelled` | **Required**
    Date and time transaction was cancelled. Time in UTC.
    Type: `string`
    Min. Length: `1`
    Format: `date-time`
    | +| `CancellationCode` | **Required**
    Cancellation code.
    Type: `string`
    Min. Length: `1`
    | +| `CancellationReason` | **Required**
    Reason transaction was cancelled.
    Type: `string`
    Min. Length: `1`
    | + +#### Example transaction cancelled webhook request body + +```json +{ + "TransactionId": "fd7f3082-72d4-46b3-8e0e-1f66e4a91e13", + "BatchId": "ab55f54a-26c3-4333-93cd-f917bb51ecad", + "EndToEndId": "08c2c49c9e094df59f342a27cb64395c", + "SchemeEndToEndId": "4026da87bb0f4a5", + "AccountId": "50daac8a-72c3-4ae5-a6e3-e71b6187dbef", + "Reference": "My payment reference 12345", + "UltimateCreditorName": "John Baker", + "UltimateCreditorAccountIdentifiers": [ + { + "Kind": "AccountId", + "Identifier": "fd75710b-4c0a-406d-a962-ef5c98836d3f" + } + ], + "UltimateDebtorName": "Clark Kent", + "UltimateDebtorAccountIdentifiers": [ + { + "Kind": "IBAN", + "Identifier": "GB33BUKB20201555555555" + } + ], + "InstructedAmount": 100.55, + "InstructedCurrency": "EUR", + "SchemePaymentMethod": "Partner 1", + "TimestampCreated": "2021-05-22T00:00:00", + "Identifiers": [ + { + "Scope": "MCCYOutboundPayments", + "Name": "SchemeEndToEndId", + "Identifier": "4026da87bb0f4a5" + } + ], + "AdditionalProperties": [ + { + "Key": "DebtorName", + "Value": "Acme Studios" + }, + { + "Key": "DebtorCountry", + "Value": "GB" + } + ], + "TimestampCancelled": "2020-09-13T09:26:15.1762781", + "CancellationCode": "RejectedByScheme", + "CancellationReason": "Contact ClearBank for more details" +}, + "Nonce":748364091 +} +``` + +#### Example webhook response + +```json +{ + "Nonce": 748364091 +} +``` + +## Multicurrency Payment Assessment Failed Webhook + +#### Request body + +```json +{ + "Type":"Payments.Mccy.PaymentAssessmentFailed", + "Version": 1, + "Payload": {...}, + "Nonce": +} +``` + +#### Payload +| Element | Description | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Error` | **Required**
    Error which caused the payment assessment to fail.
    Type: `string`
    Min. Length: `1`
    Max. Length: `280`
    | +| `UltimateDebtorName` | *Optional*
    Name of the ultimate debtor making the payment.
    Type: `string`
    Min. Length: `0`
    Max. Length: `143`
    | +| `UltimateDebtorAccount` | **Required**
    Account details of the ultimate debtor making the payment.
    Type: `string`
    Min. Length: `5`
    Max. Length: `36`
    | +| `UltimateDebtorAccountIdentifier` | **Required**
    Account identifier used to uniquely identify the ultimate debtor. Valid values are IBAN or AccountId.
    Type: `string`
    Min. Length: `1`
    | +| `UltimateDebtorAddressLine1` | **Required**
    First line of the ultimate debtor's address.
    Type: `string`
    Min. Length: `1`
    Max. Length: `70`
    | +| `UltimateDebtorAddressLine2` | *Optional*
    Second line of the ultimate debtor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateDebtorAddressLine3` | *Optional*
    Third line of the ultimate debtor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateDebtorPostCode`| **Required**
    Postcode of the ultimate debtor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `16`
    | +| `UltimateDebtorCountryCode`| **Required**
    Country code for the ultimate debtor's address. This is the 2-letter ISO country code.
    Type: `string`
    Min. Length: `2`
    Max. Length: `2`
    Pattern: `^[A-Z]{2}$`
    | +| `InstructedAmount` | **Required**
    Instructed payment amount.
    Type: `number`
    Format: `decimal`
    | +| `InstructedCurrency` | **Required**
    Currency of the instructed payment. This is the 3-digit ISO currency code.
    Type: `string`
    Min. Length: `3`
    Max. Length: `3`
    Pattern: `^[A-z]{3}$`
    | +| `Reference` | **Required**
    Reference provided by the ultimate debtor for the payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `BatchId` | **Required**
    Unique identifier for the batch in which the payment was submitted.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `EndToEndId` | **Required**
    Unique identifier provided to ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `35`
    | +| `SchemeEndToEndId` | *Optional*
    Unique identifier created by ClearBank for each payment and passed through the scheme to the creditor.
    Type: `string`
    Min. Length: `0`
    Max. Length: `15`
    | +| `UltimateCreditorIBAN` | *Optional*
    IBAN for the ultimate creditor. Mandatory only if Ultimate Creditor Account Number is not provided.
    Type: `string`
    Min. Length: `0`
    Max. Length: `34`
    | +| `UltimateCreditorAccountNumber` | *Optional*
    Account Number used to uniquely identify the ultimate creditor's account. Mandatory only if Ultimate Creditor IBAN is not provided.
    Type: `string`
    Min. Length: `0`
    Max. Length: `34`
    | +| `UltimateCreditorBic` | *Optional*
    BIC for the ultimate creditor.
    Type: `string`
    Min. Length: `8`
    Max. Length: `11`
    Pattern: `^[A-Z]{6}[A-Z2-9][A-NP-Z1-9]([A-Z0-9]{3})?$`
    | +| `UltimateCreditorName` | **Required**
    Name of the ultimate creditor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorAddressLine1` | **Required**
    First line of the ultimate creditor's address.
    Type: `string`
    Min. Length: `1`
    Max. Length: `70`
    | +| `UltimateCreditorAddressLine2` | *Optional*
    Second line of the ultimate creditor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateCreditorAddressLine3` | *Optional*
    Third line of the ultimate creditor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateCreditorPostCode` | **Required**
    Postcode of the ultimate creditor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `16`
    | +| `UltimateCreditorCountryCode` | **Required**
    Country code for the ultimate creditor's address. This is the 2-letter ISO country code.
    Type: `string`
    Min. Length: `2`
    Max. Length: `2`
    Pattern: `^[A-Z]{2}$`
    | +| `TransactionId` | **Required**
    Unique internal identifier defined by ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | + +#### Example Payment Assessment Failed webhook request body + +```json +{ + "Error":"Insufficient funds or other failure", + "UltimateDebtorName":"Richard Douglas", + "UltimateDebtorAccount":"57d06e62-efca-49e7-a71f-8eb18d72c162", + "UltimateDebtorAccountIdentifier":"AccountId", + "UltimateDebtorAddressLine1":"4th Floor, Prologue Works", + "UltimateDebtorAddressLine2":"25 Marsh St", + "UltimateDebtorAddressLine3":"Bristol", + "UltimateDebtorPostCode":"BS1 4AX", + "UltimateDebtorCountryCode":"GB", + "InstructedAmount":100.55, + "InstructedCurrency":"EUR", + "Reference":"My payment reference 12345", + "BatchId":"ab55f54a-26c3-4333-93cd-f917bb51ecad", + "EndToEndId":"08c2c49c9e094df59f342a27cb64395c", + "SchemeEndToEndId":"4026da87bb0f4a5", + "UltimateCreditorIBAN":"GB33BUKB20201555555555", + "UltimateCreditorAccountNumber":null, + "UltimateCreditorBic":"IIIGGB22", + "UltimateCreditorName":"John Baker", + "UltimateCreditorAddressLine1":"Martin Place", + "UltimateCreditorAddressLine2":"London", + "UltimateCreditorAddressLine3":null, + "UltimateCreditorPostCode":"SW1A 1AA", + "UltimateCreditorCountryCode":"GB", + "TransactionId":"fd7f3082-72d4-46b3-8e0e-1f66e4a91e13" +}, + "Nonce":748224091 +} +``` + +#### Example webhook response + +```json +{ + "Nonce": 748224091 +} +``` + + +## Multicurrency Payment Validation Failed Webhook + +#### Request body + +```json +{ + "Type":"Payments.Mccy.PaymentValidationFailed", + "Version": 1, + "Payload": {...}, + "Nonce": +} +``` + +#### Payload +| Element | Description | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Errors` | **Required**
    Error(s) which caused the payment validation to fail.
    Type: `array`
    Min. Length: `1`
    Max. Length: `140`
    | +| `UltimateDebtorName` | *Optional*
    Name of the ultimate debtor making the payment.
    Type: `string`
    Min. Length: `0`
    Max. Length: `143`
    | +| `UltimateDebtorAccount` | **Required**
    Account details of the ultimate debtor making the payment.
    Type: `string`
    Min. Length: `5`
    Max. Length: `36`
    | +| `UltimateDebtorAccountIdentifier` | **Required**
    Account identifier used to uniquely identify the ultimate debtor. Valid values are IBAN or AccountId.
    Type: `string`
    Min. Length: `1`
    | +| `UltimateDebtorAddressLine1` | **Required**
    First line of the ultimate debtor's address.
    Type: `string`
    Min. Length: `1`
    Max. Length: `70`
    | +| `UltimateDebtorAddressLine2` | *Optional*
    Second line of the ultimate debtor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateDebtorAddressLine3` | *Optional*
    Third line of the ultimate debtor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateDebtorPostCode`| **Required**
    Postcode of the ultimate debtor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `16`
    | +| `UltimateDebtorCountryCode`| **Required**
    Country code for the ultimate debtor's address. This is the 2-letter ISO country code.
    Type: `string`
    Min. Length: `2`
    Max. Length: `2`
    Pattern: `^[A-Z]{2}$`
    | +| `InstructedAmount` | **Required**
    Instructed payment amount.
    Type: `number`
    Format: `decimal`
    | +| `InstructedCurrency` | **Required**
    Currency of the instructed payment. This is the 3-digit ISO currency code.
    Type: `string`
    Min. Length: `3`
    Max. Length: `3`
    Pattern: `^[A-z]{3}$`
    | +| `Reference` | **Required**
    Reference provided by the ultimate debtor for the payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `BatchId` | **Required**
    Unique identifier for the batch in which the payment was submitted.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | +| `EndToEndId` | **Required**
    Unique identifier provided to ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Max. Length: `35`
    | +| `SchemeEndToEndId` | *Optional*
    Unique identifier created by ClearBank for each payment and passed through the scheme to the creditor.
    Type: `string`
    Min. Length: `0`
    Max. Length: `15`
    | +| `UltimateCreditorIBAN` | *Optional*
    IBAN for the ultimate creditor. Mandatory only if Ultimate Creditor Account Number is not provided.
    Type: `string`
    Min. Length: `0`
    Max. Length: `34`
    | +| `UltimateCreditorAccountNumber` | *Optional*
    Account Number used to uniquely identify the ultimate creditor's account. Mandatory only if Ultimate Creditor IBAN is not provided.
    Type: `string`
    Min. Length: `0`
    Max. Length: `34`
    +| `UltimateCreditorBic` | *Optional*
    BIC for the ultimate creditor.
    Type: `string`
    Min. Length: `8`
    Max. Length: `11`
    Pattern: `^[A-Z]{6}[A-Z2-9][A-NP-Z1-9]([A-Z0-9]{3})?$`
    | +| `UltimateCreditorName` | **Required**
    Name of the ultimate creditor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `143`
    | +| `UltimateCreditorAddressLine1` | **Required**
    First line of the ultimate creditor's address.
    Type: `string`
    Min. Length: `1`
    Max. Length: `70`
    | +| `UltimateCreditorAddressLine2` | *Optional*
    Second line of the ultimate creditor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateCreditorAddressLine3` | *Optional*
    Third line of the ultimate creditor's address.
    Type: `string`
    Min. Length: `0`
    Max. Length: `35`
    | +| `UltimateCreditorPostCode` | **Required**
    Postcode of the ultimate creditor.
    Type: `string`
    Min. Length: `1`
    Max. Length: `16`
    | +| `UltimateCreditorCountryCode` | **Required**
    Country code for the ultimate creditor's address. This is the 2-letter ISO country code.
    Type: `string`
    Min. Length: `2`
    Max. Length: `2`
    Pattern: `^[A-Z]{2}$`
    | +| `TransactionId` | **Required**
    Unique internal identifier defined by ClearBank for each payment.
    Type: `string`
    Min. Length: `1`
    Format: `GUID`
    | + +#### Example Payment Validation Failed webhook request body + +```json +{ + "Errors":[ + "Account is not enabled", + "EndToEndId already exists.", + "Account does not belong to this institution" + ], + "UltimateDebtorName":"Richard Douglas", + "UltimateDebtorAccount":"57d06e62-efca-49e7-a71f-8eb18d72c162", + "UltimateDebtorAccountIdentifier":"AccountId", + "UltimateDebtorAddressLine1":"4th Floor, Prologue Works", + "UltimateDebtorAddressLine2":"25 Marsh St", + "UltimateDebtorAddressLine3":"Bristol", + "UltimateDebtorPostCode":"BS1 4AX", + "UltimateDebtorCountryCode":"GB", + "InstructedAmount":100.55, + "InstructedCurrency":"EUR", + "Reference":"My payment reference 12345", + "BatchId":"ab55f54a-26c3-4333-93cd-f917bb51ecad", + "EndToEndId":"08c2c49c9e094df59f342a27cb64395c", + "SchemeEndToEndId":"4026da87bb0f4a5", + "UltimateCreditorIBAN":"GB33BUKB20201555555555", + "UltimateCreditorAccountNumber":null, + "UltimateCreditorBic":"IIIGGB22", + "UltimateCreditorName":"John Baker", + "UltimateCreditorAddressLine1":"Buckingham Palace", + "UltimateCreditorAddressLine2":"London", + "UltimateCreditorAddressLine3":null, + "UltimateCreditorPostCode":"SW1A 1AA", + "UltimateCreditorCountryCode":"GB", + "TransactionId":"fd7f3082-72d4-46b3-8e0e-1f66e4a91e13" +}, + "Nonce":711364091 +} +``` + +#### Example webhook response + +```json +{ + "Nonce": 711364091 +} +``` diff --git a/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx b/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx index 1a4ed4574..b60b336ce 100644 --- a/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx +++ b/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx @@ -2,3 +2,162 @@ title: "Bacs Direct Debit Instructions" order: 4 --- + +import EndpointBlock from "src/components/endpoint-block"; +import * as DD_CONSTANTS from "./managing-direct-debit-instructions.constants" + +## Managing Direct Debit Instructions + +A Direct Debit Instruction (DDI) is an authorisation to collect future payments from a nominated account. +A DDI can be submitted to ClearBank® by Service Users electronically via the Bacs Automated Direct Debit Instruction Service (AUDDIS) or sent as a paper instruction to your address to be entered via the ClearBank® API after you have validated it. +A DDI can be set up against real and virtual accounts held with ClearBank®. + +If you are transferring an existing sort code to ClearBank® that already has DDIs set up, you will need to use the API to inform us of these. + + + + + + + + + + + + + + + + + + + + + +## Returning Payments + +If a DDI has been set up against an account via AUDDIS, payments may be collected from the account on the third day; for paper instructions, payments may be collected from the following day. +The timing of the payment is in the control of the service user and does not necessarily follow immediately. + +ClearBank® will notify you with a Bacs Direct Debit Inbound Created webhook on Day 2 and confirmation of settlement will be provided with a Transaction Settled webhook on Day 3. + +If the payment cannot be applied to the account, ClearBank® will automatically raise an Automated Return of Unpaid Direct Debits (ARUDD). +If the payment has been applied, but you still want to return it, you should use these endpoints and specify the reason for return. +ClearBank® will notify you with a Bacs Direct Debit Return Created webhook. +Returns can only be initiated until 15:30 (UTC) the working day after settlement. The payment will be applied to your Bacs Suspense account on the same day and returned on Day 5. + + + + diff --git a/content-new/docs/uk-payments/chaps.mdx b/content-new/docs/uk-payments/chaps.mdx index 64d0a24fe..977160526 100644 --- a/content-new/docs/uk-payments/chaps.mdx +++ b/content-new/docs/uk-payments/chaps.mdx @@ -2,3 +2,51 @@ title: "CHAPS" order: 5 --- +import EndpointBlock from "src/components/endpoint-block" + +## CHAPS + +When sending payments via the ClearBank API, CHAPS are initiated via the POST /{vn}/Payments/CHAPS endpoint, while a confirmation of settlement is provided to you via the Transaction Settled webhook. +Please refer to [Webhooks](/docs/webhooks) for more information. + +ClearBank accounts support inbound and outbound CHAPS payments. Being that CHAPS is the UK’s high value payment scheme, there is no amount limit associated with inbound or outbound CHAPS payments. +However, you can only send CHAPS payments between 08:00 – 17:00 Monday to Friday (excluding UK public holidays). + +**CHAPS validation** + +| Element | Type | Validation | Description | +|-------------|--------|---------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `name` | string | maxLength: 140
    minLength: 1
    pattern: `^[a-zA-Z0-9\/-?:().,'+\s]*$` | **Also known as Account Holder Name**
    This the Creditor’s name.
    If max length exceeds 35 characters, this will be truncated before sending to scheme. | +| `reference` | string | maxLength: 35
    minLength: 0
    pattern: `^[a-zA-Z0-9\/-?:().,'+\s]*$` | **Also known as the Payment Reference**
    This is the Payment reference under remittance information. | + +Pattern: The character set has been extended to include all SWIFT allowed characters. Alphanumeric (uppercase and lowercase) and special characters*****.
    +*Special characters: **/** (forward slash), **-** (hyphen), **?** (question mark), **:** (colon), **(** (left parenthesis), **)** (right parenthesis), **.** (full stop), **,** (comma), **'** (apostrophe), **+** (plus sign),   (blank space). + +This endpoint uses the endToEndIdentification field as a duplicate check to ensure the request is idempotent. + + diff --git a/content-new/docs/uk-payments/confirmation-of-payee.constants.tsx b/content-new/docs/uk-payments/confirmation-of-payee.constants.tsx new file mode 100644 index 000000000..16c672232 --- /dev/null +++ b/content-new/docs/uk-payments/confirmation-of-payee.constants.tsx @@ -0,0 +1,17 @@ +import React from "react"; + +export const postUpdateAccountToOptOutOfClearBankServicesDescription = ( + <> +

    + You must provide a reason why you are opting an account out from using this service. However, you do not need to provide a reason to opt an account back in. +

    + +); + +export const postUpdateVirtualAccountToOptOutOfClearBankServicesDescription = ( + <> +

    + You must provide a reason why you are opting a virtual account out from using this service. However, you do not need to provide a reason to opt an account back in. +

    + +); diff --git a/content-new/docs/uk-payments/confirmation-of-payee.mdx b/content-new/docs/uk-payments/confirmation-of-payee.mdx index 67c76cb10..6a491c036 100644 --- a/content-new/docs/uk-payments/confirmation-of-payee.mdx +++ b/content-new/docs/uk-payments/confirmation-of-payee.mdx @@ -2,3 +2,98 @@ title: "Confirmation Of Payee (CoP)" order: 6 --- + +## Overview + +Confirmation of Payee (CoP) gives you greater assurance that you are sending payments to the intended beneficiary. It not only helps in preventing accidental, misdirected payments but also reduces the risk associated with Authorised Push Payment (APP) fraud. CoP is a scheme agnostic, peer-to-peer messaging service between accredited participants and sits completely outside of the payment journey. A CoP check can be made prior to setting up a payee or making a payment. + +ClearBank is a CoP participant and will provide this account name checking service to those customers who use ClearBank sort codes linked to our bank code. + + +import EndpointBlock from "src/components/endpoint-block"; +import * as CONSTANTS from "./confirmation-of-payee.constants" + +## CoP respond (inbound) + +Responding to a CoP request from an external participant requires us to complete a fuzzy matching check on the account in question. To do so successfully, we need the following account information: +- The name of the legal owner of the account +- Nature of funds held in the account: Personal or Business +- Operating nature of the account: Single or Joint + +For your real and virtual accounts to be CoP-ready, you will need to use the following PATCH endpoints to update your accounts: +- [PATCH /v1/Accounts/{accountId}](/docs/accounts/#amend-the-properties-of-an-existing-account) +- [PATCH /v1/Accounts/{accountId}/Virtual/{virtualAccountId}](/docs/accounts/#amend-the-properties-of-an-existing-virtual-account) + +If you have chosen to use the ClearBank CoP service, all your real and virtual accounts will be opted in by default, at the time of account creation. + +For a real or virtual account to be opted out from using this service, you can use the following PUT endpoints: +- [PUT/ v1/Cop/opt/accounts/{accountId}](#update-account-to-opt-out-from-the-clearbank-cop-service) +- [PUT/ v1/Cop/opt/accounts/{accountId}/virtual/{VirtualAccountId}](#update-virtual-account-to-opt-out-from-the-clearbank-cop-service) + +Further information about opting out from using our CoP service along with your responsibilities can be found in our Confirmation of Payee (CoP) Operating Guide. This document can be found in the Reference Documents section in the Knowledge Centre. + + + + + + +## CoP request (outbound) + +Sending a CoP request to an external participant requires us to pass the request to the participant so that they can complete a fuzzy matching check on the account in question. +To be able to send a CoP request (outbound) to an external participant, you will need to use the following POST endpoint so that the exact name registered with the payee’s account can be confirmed: +- [POST /open-banking/outbound/v1/name-verification](#confirm-the-exact-name-registered-with-the-payees-account) + +Once confirmed, we pass the result of the matching check back to you which you can then expose to your customer. Pay.UK have provided a messaging standard for you to follow. Further information about the messaging standard along with your responsibilities can be found in our Confirmation of Payee (CoP) Operating Guide. This document can be found in the Reference Documents section in the Knowledge Centre. + +### CoP requests that require secondary reference data (SRD) + +CoP checks are typically carried out on accounts that are addressable by sort code and account number, but can also be done for accounts that are addressable through secondary reference data (SRD). SRD-level checks are performed against the underlying account that is identified by the SRD rather than the name held against the sort code and account number. If an account requires SRD and it is not provided, the CoP check cannot be carried out. + +To check whether SRD will be required, use: +- [POST /open-banking/outbound/v1/srd/validate](#confirm-whether-a-sort-code-account-number-requires-srd-with-cop-requests) + +If the CoP Check requires SRD, then it must be entered in the SecondaryIdentification field in the CoP request to enable the CoP responder to identify the account. + +Supporting SRD-validated CoP checks is mandatory, however the integration that is required to support the SRD Validate endpoint, which is called ahead of the CoP check being sent is optional. Although not mandatory, this will inform your customers as to whether they need the secondary data ahead of sending the CoP check, making for a more streamlined and informed journey. + + + + \ No newline at end of file diff --git a/content-new/docs/uk-payments/faster-payments.mdx b/content-new/docs/uk-payments/faster-payments.mdx index 251f03493..e54b15420 100644 --- a/content-new/docs/uk-payments/faster-payments.mdx +++ b/content-new/docs/uk-payments/faster-payments.mdx @@ -2,3 +2,92 @@ title: "Faster payments" order: 2 --- + +import EndpointBlock from "src/components/endpoint-block" + +## Faster Payments + +When sending payments via the ClearBank API, Faster Payments are initiated via the POST /{vn}/Payments/FPS endpoint, and confirmation of settlement is provided to you via the Transaction Settled webhook. +Please refer to [Webhooks](/docs/webhooks) for more information. + +Sometimes you will need to return a faster payment; for example, because the beneficiary name does not match that of the account number, because the account has been closed or transferred, or because the beneficiary has deceased. To do so, please use this new endpoint: [/v3/payments/fps/return](#return-an-fps-payment). This can be used to return one single immediate payment. + +ClearBank accounts support inbound and outbound Faster Payments. You can send and receive Faster Payments of up to £1,000,000. +Faster Payments are not subject to a cut-off time and can be sent or received as and when required. + +Please note that payments originating overseas need to be sent using a separate endpoint: [/v2/payments/fps/singlepayment](#send-a-faster-payment-originated-overseas). + +**Faster Payments validation** + +Each payment is validated against these rules: + +| Element | Type | Validation | Description | +|-------------|--------|--------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `name` | string | maxLength: 140
    minLength: 1
    pattern: `^[a-zA-Z0-9\/\-?:().,'+\s#=!"%&*<>;{@\r\n]*$` | **Also known as Account Holder Name**
    This the Creditor’s name.
    If max length exceeds 35 characters, this will be truncated before sending to scheme. | +| `reference` | string | maxLength: 35
    minLength: 0
    pattern: `^[a-zA-Z0-9\/\-?:().,'+\s#=!"%&*<>;{@\r\n]*$` | **Also known as the Payment Reference**
    This is the Payment reference under remittance information. If the max length exceeds 18 characters, this will be truncated before sending to scheme. | + +Pattern: Alphanumeric (uppercase and lowercase) and special characters*****.
    +*****Special characters: **/** (forward slash), **-** (hyphen), **?** (question mark), **:** (colon), **(** (left parenthesis), **)** (right parenthesis), **.** (full stop), **,** (comma), **’** (right single quote), **+** (plus sign),   (blank space), **#** (hash), **=** (equals), **!** (exclamation mark), **”** (right double quote), **%** (percentage), **&** (ampersand), ***** (asterisk), **<** (less than), **>** (greater than), **;** (semicolon), **{** (left curly bracket), **@** (commercial at), **CrLf** (carriage return line feed). + +This endpoint uses the endToEndIdentification field as a duplicate check to ensure the request is idempotent. + + + + + + diff --git a/content-new/docs/uk-payments/internal-transfers.mdx b/content-new/docs/uk-payments/internal-transfers.mdx index db1237360..736275487 100644 --- a/content-new/docs/uk-payments/internal-transfers.mdx +++ b/content-new/docs/uk-payments/internal-transfers.mdx @@ -2,3 +2,20 @@ title: "Internal transfers" order: 1 --- + +import EndpointBlock from "src/components/endpoint-block"; + +## Internal Transfers + +You can initiate payments between two ClearBank multicurrency accounts that you operate. This process is known as an internal transfer request. For an internal transfer request to be processed successfully, it is imperative that both accounts are enabled for the instructed currency. + + \ No newline at end of file diff --git a/content-new/docs/uk-payments/managing-direct-debit-instructions.constants.tsx b/content-new/docs/uk-payments/managing-direct-debit-instructions.constants.tsx new file mode 100644 index 000000000..db98c3100 --- /dev/null +++ b/content-new/docs/uk-payments/managing-direct-debit-instructions.constants.tsx @@ -0,0 +1,17 @@ +import React from "react"; + +export const postCreateDdiForAccountDescription = ( + <> +

    + This endpoint uses a combination of the SUN and reference as a duplicate check and to ensure the request is idempotent. +

    + +); + +export const postCreateDdiForVirtualAccountDescription = ( + <> +

    + This endpoint uses a combination of the SUN and reference as a duplicate check and to ensure the request is idempotent. +

    + +); diff --git a/src/components/header-menu/header-menu.tsx b/src/components/header-menu/header-menu.tsx index cb2487bab..7f465e1c6 100644 --- a/src/components/header-menu/header-menu.tsx +++ b/src/components/header-menu/header-menu.tsx @@ -1,16 +1,19 @@ import React from 'react' import { hasWindow } from 'src/utils/browser.services' + import HeaderSubMenu from './header-sub-menu' + import * as Styles from './header-menu.styles' +import * as Types from'./header-meny.types' -const isMenuActive = (item) => { +const isMenuActive = (item: Types.IMenu) => { const currentPath = hasWindow() ? window.location.pathname : '' return currentPath === item.menuItem.slug } -const HeaderMenu = ({ items, currentPathname }) => { +const HeaderMenu: React.FC = ({ items }) => { return ( diff --git a/src/components/header-menu/header-meny.types.ts b/src/components/header-menu/header-meny.types.ts new file mode 100644 index 000000000..bc6f8836a --- /dev/null +++ b/src/components/header-menu/header-meny.types.ts @@ -0,0 +1,26 @@ +export interface IMenuItem { + node: { + fields: { + title: string + slug: string + id: string + } + } +} + +export interface IMenu { + menuItem: { + title: string + slug: string + } + subMenuItems: IMenuItem[] +} + +export interface IHeaderMenuProps { + items: IMenu[] +} + +export interface IHeaderSubMenuProps { + item: IMenu + isActive?: boolean +} diff --git a/src/components/header-menu/header-sub-menu.tsx b/src/components/header-menu/header-sub-menu.tsx index 3f1e22a17..a51c9dd77 100644 --- a/src/components/header-menu/header-sub-menu.tsx +++ b/src/components/header-menu/header-sub-menu.tsx @@ -1,9 +1,9 @@ import React from 'react' -import classnames from 'classnames' import * as Styles from './header-menu.styles' +import * as Types from'./header-meny.types' -const HeaderSubMenu = ({ item, isActive }) => { +const HeaderSubMenu: React.FC = ({ item, isActive }) => { return ( @@ -28,11 +28,10 @@ const HeaderSubMenu = ({ item, isActive }) => {
  • {subMenuItem.node.fields.title} + > + {subMenuItem.node.fields.title} +
  • ) })} diff --git a/src/components/header/header.styles.ts b/src/components/header/header.styles.ts index d010cbde6..a9b01bc86 100644 --- a/src/components/header/header.styles.ts +++ b/src/components/header/header.styles.ts @@ -46,7 +46,7 @@ export const BurgerIconWrapper: any = styled.div` export const LogoWrapper = styled(Link)` display: flex; height: 100%; - padding: 0 14px 0 12px; + padding: 40px 14px 40px 60px; align-items: center; svg { diff --git a/src/components/layout/layout.tsx b/src/components/layout/layout.tsx index 28052de2a..91dbe7e2c 100644 --- a/src/components/layout/layout.tsx +++ b/src/components/layout/layout.tsx @@ -6,7 +6,6 @@ import mdxComponents from '../mdxComponents' import Header from '../header' import Footer from '../footer' -import Sidebar from 'src/components/sidebar' import PageMenu from 'src/components/pageMenu' import Pagination from 'src/components/pagination' import BackToTop from 'src/components/back-to-top' @@ -42,16 +41,6 @@ const Layout: React.FunctionComponent = ({ /> - {/* - <> - {!!menuItems && ( - - )} - - */} {children} diff --git a/src/components/theme.ts b/src/components/theme.ts index fc4973797..fc51ba341 100644 --- a/src/components/theme.ts +++ b/src/components/theme.ts @@ -77,7 +77,7 @@ export const widths: Types.Widths = { } export const heights: Types.Heights = { - header: '160px' + header: '220px' } export const maxWidths: Types.MaxWidths = { From 5d9c9ade4290cd7fdd01e2c96a02196645e0c281 Mon Sep 17 00:00:00 2001 From: Anton Adamkovich Date: Mon, 27 Mar 2023 02:59:27 -0700 Subject: [PATCH 3/9] update redirects --- gatsby/node/createPages.js | 4 ++-- src/components/header/__snapshots__/header.spec.tsx.snap | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gatsby/node/createPages.js b/gatsby/node/createPages.js index 50838adb3..fc65bf049 100644 --- a/gatsby/node/createPages.js +++ b/gatsby/node/createPages.js @@ -6,14 +6,14 @@ module.exports = async ({ graphql, actions }) => { createRedirect({ fromPath: `/`, - toPath: `/docs/introduction`, + toPath: `/docs/api`, redirectInBrowser: true, isPermanent: true }) createRedirect({ fromPath: `/docs`, - toPath: `/docs/introduction`, + toPath: `/docs/api`, redirectInBrowser: true, isPermanent: true }) diff --git a/src/components/header/__snapshots__/header.spec.tsx.snap b/src/components/header/__snapshots__/header.spec.tsx.snap index 80fcf387d..0aaecdc5a 100644 --- a/src/components/header/__snapshots__/header.spec.tsx.snap +++ b/src/components/header/__snapshots__/header.spec.tsx.snap @@ -35,7 +35,7 @@ exports[`Component matches snapshot 1`] = ` display: -ms-flexbox; display: flex; height: 100%; - padding: 0 14px 0 12px; + padding: 40px 14px 40px 60px; -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; From c774eed59cef1408c454757ddbe0bb7c8db88740 Mon Sep 17 00:00:00 2001 From: Anton Adamkovich Date: Thu, 30 Mar 2023 01:25:39 -0700 Subject: [PATCH 4/9] side menu redesign --- content-new/docs/api/getting-started.mdx | 1 + content-new/docs/api/overview.mdx | 1 + content-new/docs/api/support-lify-cycle.mdx | 1 + content-new/docs/api/versioning.mdx | 1 + .../fscs-protected-deposits.mdx | 1 + .../docs/gbp-accounts/account-types.mdx | 1 + .../docs/gbp-accounts/bacs-payment-data.mdx | 1 + .../docs/gbp-accounts/manage-accounts.mdx | 1 + .../docs/gbp-accounts/payment-data.mdx | 1 + .../docs/multi-currency/account-reporting.mdx | 1 + content-new/docs/multi-currency/fx-trade.mdx | 1 + .../manage-multi-currency-accounts.mdx | 2 +- .../multi-currency-account-types.mdx | 1 + .../multi-currency-payments.mdx | 1 + content-new/docs/uk-payments.mdx | 1 - .../bacs-direct-debit-instructions.mdx | 1 + content-new/docs/uk-payments/bacs.mdx | 1 + content-new/docs/uk-payments/chaps.mdx | 2 + .../uk-payments/confirmation-of-payee.mdx | 1 + .../docs/uk-payments/faster-payments.mdx | 1 + .../docs/uk-payments/internal-transfers.mdx | 1 + gatsby/node/createPages.js | 125 +++----- .../header-menu/header-menu.styles.ts | 2 +- src/components/header-menu/header-menu.tsx | 4 +- .../header-menu/header-sub-menu.tsx | 10 +- src/components/layout/layout.styles.ts | 29 +- src/components/layout/layout.tsx | 28 +- src/components/pageMenu/page-menu.styles.ts | 82 ++--- src/components/pageMenu/page-menu.tsx | 279 +++--------------- src/components/pageMenu/page-menu.types.ts | 3 +- src/components/theme.ts | 3 +- src/containers/doc/doc.styles.ts | 2 +- src/containers/doc/doc.tsx | 60 ++-- static/assets/images/arrow-icon.png | Bin 0 -> 315 bytes 34 files changed, 193 insertions(+), 457 deletions(-) create mode 100644 static/assets/images/arrow-icon.png diff --git a/content-new/docs/api/getting-started.mdx b/content-new/docs/api/getting-started.mdx index 7448efe9b..850fd3865 100644 --- a/content-new/docs/api/getting-started.mdx +++ b/content-new/docs/api/getting-started.mdx @@ -1,6 +1,7 @@ --- title: "Getting started" order: 2 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/content-new/docs/api/overview.mdx b/content-new/docs/api/overview.mdx index 4ac633b43..00676a938 100644 --- a/content-new/docs/api/overview.mdx +++ b/content-new/docs/api/overview.mdx @@ -1,6 +1,7 @@ --- title: "Overview" order: 1 +showPageMenu: true --- ## Overview diff --git a/content-new/docs/api/support-lify-cycle.mdx b/content-new/docs/api/support-lify-cycle.mdx index 7d9236146..93ebf2c1c 100644 --- a/content-new/docs/api/support-lify-cycle.mdx +++ b/content-new/docs/api/support-lify-cycle.mdx @@ -1,6 +1,7 @@ --- title: "Support life cycle" order: 4 +showPageMenu: true --- import Callout from "src/components/callout"; diff --git a/content-new/docs/api/versioning.mdx b/content-new/docs/api/versioning.mdx index a10c04d50..a83a3586f 100644 --- a/content-new/docs/api/versioning.mdx +++ b/content-new/docs/api/versioning.mdx @@ -1,6 +1,7 @@ --- title: "Versioning" order: 3 +showPageMenu: true --- ## Versioning diff --git a/content-new/docs/embedded-banking/fscs-protected-deposits.mdx b/content-new/docs/embedded-banking/fscs-protected-deposits.mdx index 0a22e75dc..035f667a8 100644 --- a/content-new/docs/embedded-banking/fscs-protected-deposits.mdx +++ b/content-new/docs/embedded-banking/fscs-protected-deposits.mdx @@ -1,6 +1,7 @@ --- title: "FSCS protected deposites" order: 1 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/content-new/docs/gbp-accounts/account-types.mdx b/content-new/docs/gbp-accounts/account-types.mdx index f3bcd2862..a6d518d1c 100644 --- a/content-new/docs/gbp-accounts/account-types.mdx +++ b/content-new/docs/gbp-accounts/account-types.mdx @@ -1,6 +1,7 @@ --- title: "Account types" order: 1 +showPageMenu: true --- import Callout from "src/components/callout"; diff --git a/content-new/docs/gbp-accounts/bacs-payment-data.mdx b/content-new/docs/gbp-accounts/bacs-payment-data.mdx index 482dbccf4..5e7e219d5 100644 --- a/content-new/docs/gbp-accounts/bacs-payment-data.mdx +++ b/content-new/docs/gbp-accounts/bacs-payment-data.mdx @@ -1,4 +1,5 @@ --- title: "BACS Payment data" order: 4 +showPageMenu: true --- diff --git a/content-new/docs/gbp-accounts/manage-accounts.mdx b/content-new/docs/gbp-accounts/manage-accounts.mdx index 26629dcd7..370303e9f 100644 --- a/content-new/docs/gbp-accounts/manage-accounts.mdx +++ b/content-new/docs/gbp-accounts/manage-accounts.mdx @@ -1,6 +1,7 @@ --- title: "Manage accounts" order: 2 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/content-new/docs/gbp-accounts/payment-data.mdx b/content-new/docs/gbp-accounts/payment-data.mdx index 9546fc0e2..9c06c59d1 100644 --- a/content-new/docs/gbp-accounts/payment-data.mdx +++ b/content-new/docs/gbp-accounts/payment-data.mdx @@ -1,4 +1,5 @@ --- title: "Payment data" order: 3 +showPageMenu: true --- diff --git a/content-new/docs/multi-currency/account-reporting.mdx b/content-new/docs/multi-currency/account-reporting.mdx index 3cc3cc9ca..71d214b68 100644 --- a/content-new/docs/multi-currency/account-reporting.mdx +++ b/content-new/docs/multi-currency/account-reporting.mdx @@ -1,6 +1,7 @@ --- title: "Account reporting" order: 3 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/content-new/docs/multi-currency/fx-trade.mdx b/content-new/docs/multi-currency/fx-trade.mdx index e228bc888..715db8ab4 100644 --- a/content-new/docs/multi-currency/fx-trade.mdx +++ b/content-new/docs/multi-currency/fx-trade.mdx @@ -1,6 +1,7 @@ --- title: "FX Trade" order: 5 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx b/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx index e8d866764..0831c0478 100644 --- a/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx +++ b/content-new/docs/multi-currency/manage-multi-currency-accounts.mdx @@ -1,6 +1,7 @@ --- title: "Manage multi-currency accounts" order: 2 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; @@ -119,7 +120,6 @@ For more information about currencies supported by ClearBank multi-currency acco ## Virtual MCCY account - Multi-currency virtual accounts are publicly addressable accounts with their own IBAN. Also known as shadow accounts, multi-currency virtual accounts are linked to real accounts and are used to separate out funds held in real accounts for the purposes of improved reconciliation and liquidity management. Additionally, the responsibility of managing and reconciling virtual accounts rests with you, giving you complete control of such accounts. Multi-currency virtual accounts are only compatible with General Client Accounts and General Segregated Accounts, and can be created, suspended or activated and closed via the ClearBank API. diff --git a/content-new/docs/multi-currency/multi-currency-account-types.mdx b/content-new/docs/multi-currency/multi-currency-account-types.mdx index cfe61533b..5e7b582c4 100644 --- a/content-new/docs/multi-currency/multi-currency-account-types.mdx +++ b/content-new/docs/multi-currency/multi-currency-account-types.mdx @@ -1,6 +1,7 @@ --- title: "Multi-currency account types" order: 1 +showPageMenu: true --- import Callout from "src/components/callout"; diff --git a/content-new/docs/multi-currency/multi-currency-payments.mdx b/content-new/docs/multi-currency/multi-currency-payments.mdx index c88bf7c58..2fb5a04c5 100644 --- a/content-new/docs/multi-currency/multi-currency-payments.mdx +++ b/content-new/docs/multi-currency/multi-currency-payments.mdx @@ -1,6 +1,7 @@ --- title: "Multi-currency payments" order: 4 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/content-new/docs/uk-payments.mdx b/content-new/docs/uk-payments.mdx index ce6c782df..2a86c4004 100644 --- a/content-new/docs/uk-payments.mdx +++ b/content-new/docs/uk-payments.mdx @@ -3,5 +3,4 @@ title: "UK Payments" order: 3 metaTitle: "UK Payments" metaDescription: "" -showPageMenu: true --- \ No newline at end of file diff --git a/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx b/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx index b60b336ce..17b7dffd0 100644 --- a/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx +++ b/content-new/docs/uk-payments/bacs-direct-debit-instructions.mdx @@ -1,6 +1,7 @@ --- title: "Bacs Direct Debit Instructions" order: 4 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/content-new/docs/uk-payments/bacs.mdx b/content-new/docs/uk-payments/bacs.mdx index 28653714b..1182276d4 100644 --- a/content-new/docs/uk-payments/bacs.mdx +++ b/content-new/docs/uk-payments/bacs.mdx @@ -1,4 +1,5 @@ --- title: "Bacs" order: 3 +showPageMenu: true --- diff --git a/content-new/docs/uk-payments/chaps.mdx b/content-new/docs/uk-payments/chaps.mdx index 977160526..016fefc08 100644 --- a/content-new/docs/uk-payments/chaps.mdx +++ b/content-new/docs/uk-payments/chaps.mdx @@ -1,7 +1,9 @@ --- title: "CHAPS" order: 5 +showPageMenu: true --- + import EndpointBlock from "src/components/endpoint-block" ## CHAPS diff --git a/content-new/docs/uk-payments/confirmation-of-payee.mdx b/content-new/docs/uk-payments/confirmation-of-payee.mdx index 6a491c036..6bb078460 100644 --- a/content-new/docs/uk-payments/confirmation-of-payee.mdx +++ b/content-new/docs/uk-payments/confirmation-of-payee.mdx @@ -1,6 +1,7 @@ --- title: "Confirmation Of Payee (CoP)" order: 6 +showPageMenu: true --- ## Overview diff --git a/content-new/docs/uk-payments/faster-payments.mdx b/content-new/docs/uk-payments/faster-payments.mdx index e54b15420..05984264f 100644 --- a/content-new/docs/uk-payments/faster-payments.mdx +++ b/content-new/docs/uk-payments/faster-payments.mdx @@ -1,6 +1,7 @@ --- title: "Faster payments" order: 2 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block" diff --git a/content-new/docs/uk-payments/internal-transfers.mdx b/content-new/docs/uk-payments/internal-transfers.mdx index 736275487..53807052b 100644 --- a/content-new/docs/uk-payments/internal-transfers.mdx +++ b/content-new/docs/uk-payments/internal-transfers.mdx @@ -1,6 +1,7 @@ --- title: "Internal transfers" order: 1 +showPageMenu: true --- import EndpointBlock from "src/components/endpoint-block"; diff --git a/gatsby/node/createPages.js b/gatsby/node/createPages.js index fc65bf049..e7825db3d 100644 --- a/gatsby/node/createPages.js +++ b/gatsby/node/createPages.js @@ -1,7 +1,30 @@ const path = require('path') const Helpers = require('./helpers') -module.exports = async ({ graphql, actions }) => { +const ALL_PAGES_SCHEMA = ` + { + allPages: allMdx( + filter: { + frontmatter: { webhook: { ne: true }, order: { gt: 0 } } + } + sort: { fields: frontmatter___order } + ) { + edges { + node { + fields { + id + order + slug + title + } + body + } + } + } + } +` + +module.exports = async ({ graphql, actions, reporter }) => { const { createPage, createRedirect } = actions createRedirect({ @@ -18,85 +41,35 @@ module.exports = async ({ graphql, actions }) => { isPermanent: true }) - return new Promise((resolve, reject) => { - resolve( - graphql( - ` - { - allPages: allMdx( - filter: { - frontmatter: { webhook: { ne: true }, order: { gt: 0 } } - } - sort: { fields: frontmatter___order } - ) { - edges { - node { - fields { - id - order - slug - title - } - body - } - } - } - } - ` - ).then(async result => { - if (result.errors) { - console.log(result.errors) // eslint-disable-line no-console - reject(result.errors) - } + const result = await graphql(ALL_PAGES_SCHEMA) - const { allPages } = result.data - const rootLevelPages = allPages.edges.filter( - ({ node }) => Helpers.isRootLevelDocContainer(node.fields.slug) - ) - const menuItems = await Helpers.buildMenu(rootLevelPages, graphql) + if (result.errors) { + console.log(result.errors) + reporter.panicOnBuild(`Error while running GraphQL query.`) + return + } - // Create blog posts pages. - const pagesRequests = await allPages.edges.map(async ({ node }) => { - const { slug, id } = node.fields - const regexFilter = `/^${slug}/` - const homepage = slug === '/' + const { allPages } = result.data + const rootLevelPages = allPages.edges.filter( + ({ node }) => Helpers.isRootLevelDocContainer(node.fields.slug) + ) + const menuItems = await Helpers.buildMenu(rootLevelPages, graphql) - if (homepage) { - return Promise.resolve({ - path: '/', - component: path.resolve('./src/pages/homepage.tsx'), - context: { - slug: '/introduction', - menuItems - } - }) - } else { - return Promise.resolve({ - path: slug ? slug : '/', - component: path.resolve('./src/templates/pages.tsx'), - context: { - id, - slug, - menuItems, - regexFilter - } - }) - } - }) + // Create blog posts pages. + allPages.edges.forEach(({ node }) => { + const { slug, id } = node.fields + const regexFilter = `/^${slug}/` - const pages = await Promise.all(pagesRequests) + createPage({ + path: slug || '/', + component: path.resolve('./src/templates/pages.tsx'), + context: { + id, + slug, + menuItems, + regexFilter + } + }) - pages.forEach(({ path, component, context }) => { - // skip making pages for sub pages - if (Helpers.isRootLevelDocContainer(path)) { - createPage({ - path, - context, - component - }) - } - }) - }) - ) }) } diff --git a/src/components/header-menu/header-menu.styles.ts b/src/components/header-menu/header-menu.styles.ts index 73fabf288..1afbb6a9a 100644 --- a/src/components/header-menu/header-menu.styles.ts +++ b/src/components/header-menu/header-menu.styles.ts @@ -41,7 +41,7 @@ export const Underline = styled.div` border-radius: 10px; ` -export const Title = styled(LinkBase)` +export const Title = styled(LinkBase)<{ isActive?: boolean }>` line-height: 38px; font-size: 25px; font-weight: ${props => props.isActive ? 500 : 400}; diff --git a/src/components/header-menu/header-menu.tsx b/src/components/header-menu/header-menu.tsx index 7f465e1c6..db1a9443a 100644 --- a/src/components/header-menu/header-menu.tsx +++ b/src/components/header-menu/header-menu.tsx @@ -9,8 +9,8 @@ import * as Types from'./header-meny.types' const isMenuActive = (item: Types.IMenu) => { const currentPath = hasWindow() ? window.location.pathname : '' - - return currentPath === item.menuItem.slug + + return currentPath.startsWith(item.menuItem.slug) } const HeaderMenu: React.FC = ({ items }) => { diff --git a/src/components/header-menu/header-sub-menu.tsx b/src/components/header-menu/header-sub-menu.tsx index a51c9dd77..93e01a14a 100644 --- a/src/components/header-menu/header-sub-menu.tsx +++ b/src/components/header-menu/header-sub-menu.tsx @@ -21,15 +21,11 @@ const HeaderSubMenu: React.FC = ({ item, isActive })
    {item.subMenuItems?.map(subMenuItem => { - const [hash] = subMenuItem.node.fields.slug.match(new RegExp(/[^\/]+$/)) - const link = `${item.menuItem.slug}#${hash}` + const link = subMenuItem.node.fields.slug return ( -
  • - +
  • + {subMenuItem.node.fields.title}
  • diff --git a/src/components/layout/layout.styles.ts b/src/components/layout/layout.styles.ts index 816f4c89f..f0d727f08 100644 --- a/src/components/layout/layout.styles.ts +++ b/src/components/layout/layout.styles.ts @@ -65,19 +65,6 @@ export const HeaderWrapper = styled.header` z-index: 1; ` -export const LeftSidebarWrapper = styled.nav` - grid-area: sidebarLeft; - -ms-grid-column: 1; - -ms-grid-row-span: 2; - -ms-grid-row: 2; - background: ${colors.brandGrayLightest}; - display: none; - - @media screen and (min-width: ${breakpoints.large}) { - display: block; - } -` - export const ContentWrapper = styled.article` grid-area: content; -ms-grid-column: 2; @@ -117,24 +104,10 @@ export const ContentWrapper = styled.article` ` export const RightSidebarWrapper = styled.aside` + max-width: 380px; grid-area: sidebarRight; -ms-grid-column: 3; -ms-grid-row: 2; - padding: 60px 20px 40px 20px; - - @media screen and (min-width: ${breakpoints.medium}) { - padding: 80px 60px 40px 60px; - } - - @media screen and (min-width: ${breakpoints.large}) { - padding: 0 60px 0 0; - min-width: ${widths.sidebarRight}; // prevent sidebar-collapse on pages without sidebar - box-sizing: content-box; // add padding to min-width - } - - @media screen and (min-width: ${breakpoints.xLarge}) { - padding: 0 100px 0 0; - } ` export const InnerContentWrapper = styled.main` flex: 1 1 auto; diff --git a/src/components/layout/layout.tsx b/src/components/layout/layout.tsx index 91dbe7e2c..dfa082aa5 100644 --- a/src/components/layout/layout.tsx +++ b/src/components/layout/layout.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useMemo } from 'react' import { MDXProvider } from '@mdx-js/react' import ThemeProvider from '../themeProvider' import mdxComponents from '../mdxComponents' @@ -11,6 +11,8 @@ import Pagination from 'src/components/pagination' import BackToTop from 'src/components/back-to-top' import HeaderMenu from 'src/components/header-menu' +import { hasWindow } from 'src/utils/browser.services' + import * as Styles from './layout.styles' import * as Types from './layout.types' @@ -23,12 +25,28 @@ const Layout: React.FunctionComponent = ({ const { pathname, hash } = location const { menuItems } = pageContext + // const headings = useMemo(() => { + // if (!hasWindow()) { + // return []; + // } + + const mdxTitles: HTMLElement[] = Array.from(document.querySelectorAll('.page .page-menu-entry')) + + const headings = mdxTitles + .map(mdxTitle => ({ + tag: mdxTitle.tagName, + parent: mdxTitle.closest('.page').id, + title: mdxTitle.textContent, + id: mdxTitle.id + })) + .filter((entry: any) => entry.id !== '') + // }, [data]) + if (!data || !data.mdx || !data.mdx.frontmatter) { return null } const { metaTitle: pageTitle, showPageMenu } = data.mdx.frontmatter - const showRightSidebar = showPageMenu === null ? true : showPageMenu !== false return ( @@ -39,7 +57,7 @@ const Layout: React.FunctionComponent = ({ menuItems={pageContext.menuItems} currentPageURL={`${pathname}${hash}`} /> - + @@ -48,11 +66,11 @@ const Layout: React.FunctionComponent = ({ - {showRightSidebar && ( + {showPageMenu && ( <> {/* PageHeader only visible on small and medium viewport */} {pageTitle} - + )} diff --git a/src/components/pageMenu/page-menu.styles.ts b/src/components/pageMenu/page-menu.styles.ts index b0c047039..a9c3e2dcd 100644 --- a/src/components/pageMenu/page-menu.styles.ts +++ b/src/components/pageMenu/page-menu.styles.ts @@ -5,16 +5,11 @@ import { colors, widths, breakpoints } from 'src/components/theme' export const Container = styled.div` color: ${colors.brandLight}; user-select: none; + padding: 50px 23px 0px 23px; + border-left: 3px solid ${colors.boulderapprox}; @media screen and (min-width: ${breakpoints.large}) { position: sticky; - top: 100px; // header height + margin top where it becomes stuck - bottom: 0; - width: ${widths.sidebarRight}; - height: calc(100vh - 60px); // 60px header top - margin-top: 40px; - margin-bottom: 80px; - padding-right: 15px; // reserved space for scrollbar overflow-y: auto; overscroll-behavior: contain; } @@ -24,75 +19,56 @@ export const Title = styled.h5` margin: 0; color: ${colors.body}; font-weight: 600; - font-size: 22px; + font-size: 32px; cursor: default; - line-height: 1.25; // 25px + line-height: 38px; ` export const List = styled.ul` list-style: none; - margin-left: ${({ level }) => level * 10}px; - - ${({ level }) => - level === 0 && - css` - padding-bottom: 40px; - `} - - @media screen and (min-width: ${breakpoints.large}) { - margin-left: ${({ level }) => level * 20}px; - } + margin-top: 15px; ` export const Entry = styled.li` - margin-top: 20px; - - &:first-of-type { - margin-top: 10px; - } + // line-height: 38px; + // font-size: 20px; ` -export const SecondLevelEntry = styled(Entry)` - margin-top: 10px; -` +export const SecondLevelEntry = styled(Entry)`` export const Link = styled.a` - display: block; - color: ${colors.ceruleanBlue}; - font-size: 14px; - font-weight: 600; - transition: none; + text-decoration: none; + cursor: pointer; + color: ${colors.brandDark}; &:hover { - color: ${colors.brandSecondaryDarkest}; + color: ${colors.wedgewoodapprox}; } ` -export const FirstLevelLink = styled(Link)` - font-weight: 600; +export const FirstLevelListItem = styled.li` + font-weight: 500; + font-size: 20px; + line-height: 38px; +` - @media screen and (min-width: ${breakpoints.large}) { - padding-left: 7px; - border-left: 3px solid transparent; +export const SecondLevelListItem = styled.li` + margin-top: 5px; + font-weight: 400; + line-height: 38px; + margin-left: 30px; - ${({ isHighlighted }) => - isHighlighted && - css` - border-left-color: ${colors.highlightAqua}; - `} - } + list-style-image: url(/assets/images/arrow-icon.png); ` -export const SecondLevelLink = styled(Link)` +export const ThirdLevelListItem = styled.li` font-weight: 400; + line-height: 38px; + font-size: 16px; + margin-left: 60px; - ${({ isHighlighted }) => - isHighlighted && - css` - color: ${colors.brandSecondaryDarkest}; - font-weight: 600; - `} -` + list-style-image: url(/assets/images/arrow-icon.png); +`; export const Type = styled.span` margin-right: 5px; diff --git a/src/components/pageMenu/page-menu.tsx b/src/components/pageMenu/page-menu.tsx index e9fe80804..66c5142c8 100644 --- a/src/components/pageMenu/page-menu.tsx +++ b/src/components/pageMenu/page-menu.tsx @@ -1,4 +1,4 @@ -import React, { useState, useRef, useLayoutEffect } from 'react' +import React, { useState, useRef, useLayoutEffect, useMemo } from 'react' import throttle from 'lodash.throttle' import flatten from 'lodash.flatten' import kebabCase from 'lodash.kebabcase' @@ -8,253 +8,50 @@ import { hasWindow } from 'src/utils/browser.services' import * as Types from './page-menu.types' import * as Styles from './page-menu.styles' -const SubmenuMdx: React.FunctionComponent = ({ - submenu, - activeElementIds -}): JSX.Element => { - // Prevent widows - const formatTitle = (title: string): string => { - return title.replace(/\s(?=[^\s]*$)/g, '\u00A0') - } - - return ( - - {submenu.map(({ id, title }, index: number) => { - const isHighlighted = activeElementIds.includes(id) - - // ignore first entry that is identically to the headlines - if (index === 0) { - return null - } - - return ( - - - {formatTitle(title)} - - - ) - })} - - ) -} - -const PageMenu: React.FunctionComponent = ({ - data -}): JSX.Element => { - const [submenusMdx, setSubmenusMdx] = useState([]) - const [scrollPosition, setScrollPosition] = useState(0) - const [activeParentIds, setActiveParentIds] = useState([]) - const [activeElementIds, setActiveElementsIds] = useState([]) - const scrollYPositionPrev = useRef(0) - - const contentInSubdirectory = new RegExp(/^\/docs\/([\w-_]+\/)[\w-_]+\/?$/) - - // calculate scrollPosition - useLayoutEffect(() => { - if (!hasWindow) { - return - } - - const handleScroll = () => { - const currentScrollPosition = window.scrollY - - setScrollPosition(oldScrollPosition => { - scrollYPositionPrev.current = oldScrollPosition - - return currentScrollPosition - }) - } - - const throttledScroll = throttle(handleScroll, 100) - - window.addEventListener('scroll', throttledScroll) - - return () => { - window.removeEventListener('scroll', throttledScroll) - } - }, []) - - // create menu - useLayoutEffect(() => { - if (!hasWindow) { - return - } - - const mdxTitles: HTMLElement[] = Array.from( - document.querySelectorAll('.page .page-menu-entry') - ) - - const mdxTitlesDomElements = mdxTitles - .map(mdxTitle => ({ - parent: mdxTitle.closest('.page').id, - title: mdxTitle.textContent, - id: mdxTitle.id - })) - // remove entries with missing attributes - .filter((entry: any) => - Object.values(entry).every(value => value !== null) +const mapHeadingToComponent = (heading: any) => { + switch(heading.tag) { + case 'H1': + return ( + + + {heading.title} + + ) - .filter((entry: any) => entry.id !== '') - - // group subpages by parent - const mappedMdxTitles = mdxTitlesDomElements.reduce( - (total, { parent, id, title }) => { - const entryNew = { - id, - title - } - - total[parent] = - parent in total - ? total[parent].concat([entryNew]) - : (total[parent] = [entryNew]) - - return total - }, - {} as any - ) - - setSubmenusMdx(mappedMdxTitles) - }, []) - - // find active parent - useLayoutEffect(() => { - if (!hasWindow) { - return - } - - if (window.matchMedia('(max-width: 991px)').matches) { - return - } - - const inViewCheckpoint = window.scrollY + window.innerHeight // bottom of viewport - - // merge mainnav - const levelAlphaEntries = flatten(Object.keys(submenusMdx)) - - const sectionsInViewport = levelAlphaEntries.filter((entry: any) => { - if (entry === '') { - return false - } - - const section: HTMLElement = document.querySelector(`#${entry}`) - - // section not found in main content - if (section === null) { - return false - } - - const elementStart = section.offsetTop - const elementEnd = section.offsetTop + section.offsetHeight - - if (elementStart <= inViewCheckpoint && elementEnd >= inViewCheckpoint) { - return true - } - - return false - }) - - setActiveParentIds(sectionsInViewport) - }, [submenusMdx, scrollPosition]) - - // find active subentries - useLayoutEffect(() => { - if (!hasWindow) { - return - } - - if (window.matchMedia('(max-width: 991px)').matches) { - return - } - - // lower screen border - const inViewCheckpoint = window.scrollY + window.innerHeight // bottom of viewport - - // merge subnav - const lowerLevelEntries = flatten(Object.values(submenusMdx)) - const sectionsInViewport = lowerLevelEntries - .filter((entry: any) => { - if (entry.id === '') { - return false - } - - const section: HTMLElement = document.querySelector(`#${entry.id}`) - - // section not found in main content - if (section === null) { - return false - } - - const parent: HTMLElement = section.closest('.page-menu-entry-parent') - - if (parent === null) { - return false - } - - const container = parent.offsetParent - const containerOffset = (container as HTMLElement).offsetTop - - const parentStart = containerOffset + parent.offsetTop - const parentEnd = - containerOffset + parent.offsetTop + parent.offsetHeight - - if (parentStart <= inViewCheckpoint && parentEnd >= inViewCheckpoint) { - return true - } - - return false - }) - .map((entry: any) => entry.id) - - setActiveElementsIds(sectionsInViewport) - }, [submenusMdx, scrollPosition]) - - if (!data || !data.pageContent || !data.pageContent.edges) { - return null + case 'H2': + return ( + + + {heading.title} + + + ); + case 'H3': + return ( + + + {heading.title} + + + ); + case 'H4': + return; + default: + return null; } +} - const firstLevelEntries = data.pageContent.edges - .map(({ node }: any) => node.fields) - .filter((node: any) => contentInSubdirectory.test(node.slug)) - if (!firstLevelEntries.length) { - return null - } +const PageMenu: React.FC = ({ + headings +}) => { return ( - On this page - - {firstLevelEntries.map(({ title }: any, index: number) => { - const titleConverted = kebabCase(title.toLowerCase()) - - const target = `#${titleConverted}` - const submenuMdx = submenusMdx[titleConverted] || [] - const isActiveParent = activeParentIds.includes(titleConverted) - const hasChildren = !!submenuMdx.length - - return ( - - - {title} - - {hasChildren && ( - - )} - - ) - })} + On this page: + + + {headings.map(heading => mapHeadingToComponent(heading))} ) diff --git a/src/components/pageMenu/page-menu.types.ts b/src/components/pageMenu/page-menu.types.ts index 637e6483f..b6394ec9a 100644 --- a/src/components/pageMenu/page-menu.types.ts +++ b/src/components/pageMenu/page-menu.types.ts @@ -1,8 +1,9 @@ export interface PageMenuProps { - data: any + headings: any } export interface PageSubmenuProps { submenu: any activeElementIds: any + target: any } diff --git a/src/components/theme.ts b/src/components/theme.ts index fc51ba341..ced57af6a 100644 --- a/src/components/theme.ts +++ b/src/components/theme.ts @@ -70,8 +70,6 @@ export const widths: Types.Widths = { logo: '244px', gutter: '20px', container: '1400px', - sidebarLeft: '270px', - sidebarRight: '200px', content: '1200px', dropdown: '270px' } @@ -184,6 +182,7 @@ export const colors = { concrete: '#F2F2F2', // V2 alto: '#E0E0E0', // V2 wedgewoodapprox: '#478E96', + boulderapprox: '#747474', // New branding colours V2 - TODO: these color vars need sorting out billionaireBlue: '#000000', diff --git a/src/containers/doc/doc.styles.ts b/src/containers/doc/doc.styles.ts index a95f32f78..19827cc4e 100644 --- a/src/containers/doc/doc.styles.ts +++ b/src/containers/doc/doc.styles.ts @@ -39,7 +39,7 @@ export const Page = styled.section` } ` -export const ShareContainer = styled.div` +export const ShareContainer = styled.div<{ isFirstEntry?: boolean }>` position: absolute; right: 0; // first headline has larger margin top diff --git a/src/containers/doc/doc.tsx b/src/containers/doc/doc.tsx index 7ac3d3707..9cebc4855 100644 --- a/src/containers/doc/doc.tsx +++ b/src/containers/doc/doc.tsx @@ -1,13 +1,15 @@ import React from 'react' import { MDXRenderer } from 'gatsby-plugin-mdx' +import kebabCase from 'lodash.kebabcase' + import { Layout } from 'src/components' import GithubConnector from 'src/components/github-connector' -import 'src/components/styles.css' + import config from '../../../config' -import kebabCase from 'lodash.kebabcase' import * as Styles from './doc.styles' +import 'src/components/styles.css' export default function Doc(props: any) { const { data } = props; @@ -16,46 +18,28 @@ export default function Doc(props: any) { return null } - const contentInSubdirectory = new RegExp(/^\/docs\/([\w-_]+\/)[\w-_]+\/?$/) - - const pageContent = data.pageContent.edges.map(({ node }, index: number, array: any[]) => { - const { id, slug, title } = node.fields - const isInSubdirectory = contentInSubdirectory.test(slug) - const hasSiblings = array.length > 1 - - const isPageInAFilledSubmenu = isInSubdirectory && hasSiblings - const isPageWithoutSubmenu = !isInSubdirectory && !hasSiblings - - // do not generate empty root pages in subdirectories - if (!isPageInAFilledSubmenu && !isPageWithoutSubmenu) { - return null - } - - const pageId = isPageInAFilledSubmenu ? kebabCase(title.toLowerCase()) : null - - const filePath = `${config.header.githubDocsRoot}${slug}.mdx` - - return ( - - {node.body} - - - - - ) - }) - - // if you want a main page title for the whole thing const pageTitle = data.mdx.fields.title + const pageId = kebabCase(data.mdx.fields.title.toLowerCase()) return ( - - {pageTitle} - - <> - {pageContent} - + + + {pageTitle} + + {data.pageContent.edges.map(({ node }, index: number) => { + const filePath = `${config.header.githubDocsRoot}${node.fields.slug}.mdx` + + return ( +
    + {node.body} + + + +
    + ) + })} +
    ) } diff --git a/static/assets/images/arrow-icon.png b/static/assets/images/arrow-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b1d2570c591f3dc996b66305c35013e1c8e7668f GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^qChOj!3HFa+MYK6Db50q$YKTtZeb8+WSBKa0w~B> z9OUlAueQOmWG&p{>Xi;l}kn)BWm;Mc$hqO-ypW74YEmhUMC& zXPfx0CeCL!U8(E(p2J<`)a-fB{xok;{P<_LUjCbz)gLDQ6+Xe7wq+3m*F@g4yi;dR zZ3>Qhy!>-y&?3& Date: Fri, 31 Mar 2023 05:17:50 -0700 Subject: [PATCH 5/9] add footer layout --- src/components/footer/footer.styles.ts | 93 ++++++++++----------- src/components/footer/footer.tsx | 36 ++++---- src/components/header/header.types.ts | 2 - src/components/layout/layout.tsx | 28 +------ src/components/pageMenu/page-menu.styles.ts | 63 ++++++-------- src/components/pageMenu/page-menu.tsx | 69 +++++++++------ src/components/pageMenu/page-menu.types.ts | 1 - src/components/theme.ts | 1 + src/containers/doc/doc.tsx | 2 +- 9 files changed, 141 insertions(+), 154 deletions(-) diff --git a/src/components/footer/footer.styles.ts b/src/components/footer/footer.styles.ts index 36e156761..62a993e82 100644 --- a/src/components/footer/footer.styles.ts +++ b/src/components/footer/footer.styles.ts @@ -1,70 +1,63 @@ import styled from 'styled-components' import { Box } from 'rebass' -import { colors, breakpoints } from 'src/components/theme' +import { colors } from 'src/components/theme' -export const Container: any = styled(Box)` - display: flex; - flex-direction: column; - padding-top: 20px; - border-top: dashed 1px ${colors.alto}; - - @media screen and (min-width: ${breakpoints.large}) { - align-items: start; - flex-direction: row; - justify-content: space-between; - } +export const Container = styled(Box).attrs(() => ({ mt: '140px' }))`` - @media screen and (min-width: ${breakpoints.large}) { - padding: 30px; - } +export const MenuContainer = styled.div` + display: flex; + justify-content: space-between; + margin: 0 7%; + padding: 0 5%; + border-bottom: 1px solid ${colors.mischkaapprox}; ` -export const LogoWrapper: any = styled.div` - max-width: 170px; - display: block; - margin: auto; - margin-bottom: 30px; - margin-top: 30px; - - @media screen and (min-width: ${breakpoints.large}) { - margin-top: 0; - } +export const ColumnContainer = styled.div` + max-width: 200px; ` -export const CopywriteWrapper = styled.div` - text-align: center; - margin-bottom: 40px; - - @media screen and (min-width: ${breakpoints.medium}) { - margin-top: 30px; - } +export const Title = styled.a` + text-decoration: none; + cursor: pointer; + font-weight: 600; + font-size: 20px; + color: ${colors.brandDark} +`; + +export const SubTitle = styled.a` + line-height: 20px; + text-decoration: none; + cursor: pointer; + font-weight: 400; + font-size: 18px; + color: ${colors.brandDark} +` - @media screen and (min-width: ${breakpoints.large}) { - padding-right: 50px; // space for to top button - } +export const List = styled.ul` + margin-top: 40px; + list-style: none; + padding: 0; ` -export const CopyContainer = styled.div` - padding: 0 20px; +export const ListItem = styled.li` + margin-bottom: 20px; ` -export const Copy = styled.p` +export const LogoWrapper = styled.div` + max-width: 170px; display: block; - width: 100%; - color: ${colors.brandSecondaryDarker}; - font-size: 14px; - - @media screen and (min-width: ${breakpoints.large}) { - padding-right: 55px; + margin: 40px 0px 20px 40px; +` - &:first-child { - margin-top: 30px; - } - } +export const CopywriteWrapper = styled.div` + text-align: center; + margin-bottom: 40px; ` -export const Copywrite = styled.span` - white-space: nowrap; +export const Copywrite = styled.p` + max-width: 70%; + margin-left: auto; + text-align: right; color: ${colors.brandSecondaryDarker}; ` diff --git a/src/components/footer/footer.tsx b/src/components/footer/footer.tsx index 8de0593b2..f15cecd36 100644 --- a/src/components/footer/footer.tsx +++ b/src/components/footer/footer.tsx @@ -4,26 +4,34 @@ import Logo from 'src/components/logo' import * as Styles from './footer.styles' -const Footer:React.FunctionComponent = (): JSX.Element => ( +const Footer: React.FC<{}> = ({ items }) => ( - - - Copyright ClearBank Ltd. Authorised by the Prudential Regulation Authority - and regulated by the Financial Conduct Authority and the Prudential - Regulation Authority (Financial Services Register number: 754568). - Registered Address: ClearBank, 4th Floor, Prologue Works, 25 Marsh St, Bristol BS1 4AX. - - - ClearBank® provides customers with a Definitive Services Agreement, which covers the provision of indirect access services. - Code of Conduct for Indirect Access Providers - - + + {items.map(item => ( + + + {item.menuItem.title} + + + {item.subMenuItems.map(subMenuItem => ( + + + {subMenuItem.node.fields.title} + + + ))} + + + ))} + + - © Copyright {new Date().getFullYear()} ClearBank® + Copyright ClearBank Ltd. Authorised by the Prudential Regulation Authority and regulated by the Financial Conduct Authority and the Prudential Regulation Authority + (Financial Services Register number: 754568). Registered Address: ClearBank, 4th Floor, Prologue Works, 25 Marsh St, Bristol BS1 4AX diff --git a/src/components/header/header.types.ts b/src/components/header/header.types.ts index 6f1e9c6fa..2b28d1856 100644 --- a/src/components/header/header.types.ts +++ b/src/components/header/header.types.ts @@ -1,4 +1,2 @@ export interface HeaderProps { - menuItems: any[] - currentPageURL: string } diff --git a/src/components/layout/layout.tsx b/src/components/layout/layout.tsx index dfa082aa5..d057ea877 100644 --- a/src/components/layout/layout.tsx +++ b/src/components/layout/layout.tsx @@ -11,8 +11,6 @@ import Pagination from 'src/components/pagination' import BackToTop from 'src/components/back-to-top' import HeaderMenu from 'src/components/header-menu' -import { hasWindow } from 'src/utils/browser.services' - import * as Styles from './layout.styles' import * as Types from './layout.types' @@ -25,23 +23,6 @@ const Layout: React.FunctionComponent = ({ const { pathname, hash } = location const { menuItems } = pageContext - // const headings = useMemo(() => { - // if (!hasWindow()) { - // return []; - // } - - const mdxTitles: HTMLElement[] = Array.from(document.querySelectorAll('.page .page-menu-entry')) - - const headings = mdxTitles - .map(mdxTitle => ({ - tag: mdxTitle.tagName, - parent: mdxTitle.closest('.page').id, - title: mdxTitle.textContent, - id: mdxTitle.id - })) - .filter((entry: any) => entry.id !== '') - // }, [data]) - if (!data || !data.mdx || !data.mdx.frontmatter) { return null } @@ -53,10 +34,7 @@ const Layout: React.FunctionComponent = ({ -
    +
    @@ -70,12 +48,12 @@ const Layout: React.FunctionComponent = ({ <> {/* PageHeader only visible on small and medium viewport */} {pageTitle} - + )} -