Skip to content

Commit

Permalink
Merge pull request #284 from radixdlt/DO-1241-cloudflare-main
Browse files Browse the repository at this point in the history
DO-1241 / main / move cloudflare secret to aws
  • Loading branch information
dhedey authored May 14, 2023
2 parents 63b6901 + ac3990b commit 4586d93
Show file tree
Hide file tree
Showing 11 changed files with 4,729 additions and 6,650 deletions.
27 changes: 25 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,19 @@ jobs:
- docker-database-migrations-gcr
- setup-tags
if: github.ref == 'refs/heads/develop'
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
- uses: ./.github/actions/fetch-secrets
with:
role_name: "arn:aws:iam::308190735829:role/gh-babylon-gateway-secrets-read-access"
app_name: "babylon-gateway"
step_name: "deploy-on-mardunet"
secret_prefix: "CF_GITHUB_WORKER"
secret_name: "github-actions/radixdlt/babylon-gateway/cloudflare"
parse_json: true
- name: Process ci.env
run: |
export $(grep -v '^#' ./deployment/ci.env | xargs)
Expand All @@ -119,7 +130,7 @@ jobs:
run: |
curl --silent --show-error --fail --location --request POST 'https://github-worker.radixdlt.com/repos/radixdlt/${{secrets.DISPATCH_REPO}}/dispatches' \
--header 'Accept: application/vnd.github.v3+json' \
--header 'Authorization: Basic ${{secrets.CF_GITHUB_WORKER_ENCODED_BASIC_AUTH}}' \
--header 'Authorization: Basic ${{env.CF_GITHUB_WORKER_ENCODED_BASIC_AUTH}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"event_type": "${{env.EVENT_TYPE}}",
Expand Down Expand Up @@ -187,7 +198,19 @@ jobs:
- docker-database-migrations-gcr
- setup-tags
if: github.event_name == 'pull_request'
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
- uses: ./.github/actions/fetch-secrets
with:
role_name: "arn:aws:iam::308190735829:role/gh-babylon-gateway-secrets-read-access"
app_name: "babylon-gateway"
step_name: "deploy-pr"
secret_prefix: "CF_GITHUB_WORKER"
secret_name: "github-actions/radixdlt/babylon-gateway/cloudflare"
parse_json: true
- name: setup "namespace_postfix"
run: |
pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
Expand All @@ -198,7 +221,7 @@ jobs:
run: |
curl --silent --show-error --fail --location --request POST 'https://github-worker.radixdlt.com/repos/radixdlt/${{secrets.DISPATCH_REPO}}/dispatches' \
--header 'Accept: application/vnd.github.v3+json' \
--header 'Authorization: Basic ${{secrets.CF_GITHUB_WORKER_ENCODED_BASIC_AUTH}}' \
--header 'Authorization: Basic ${{env.CF_GITHUB_WORKER_ENCODED_BASIC_AUTH}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"event_type": "${{env.EVENT_TYPE}}",
Expand Down
14 changes: 13 additions & 1 deletion .github/workflows/pr-namespace-deletion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@ jobs:
dispatch-pr-hns-deletion-events:
if: github.event.pull_request.merged == true
runs-on: ubuntu-22.04
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
- uses: ./.github/actions/fetch-secrets
with:
role_name: "arn:aws:iam::308190735829:role/gh-babylon-gateway-secrets-read-access"
app_name: "babylon-gateway"
step_name: "dispatch-pr-hns-deletion-events"
secret_prefix: "CF_GITHUB_WORKER"
secret_name: "github-actions/radixdlt/babylon-gateway/cloudflare"
parse_json: true
- name: Get PR HSN
run: |
pull_number=${{ github.event.number }}
Expand All @@ -17,7 +29,7 @@ jobs:
run: |
curl --silent --show-error --fail --location --request POST 'https://github-worker.radixdlt.com/repos/radixdlt/${{secrets.DISPATCH_REPO}}/dispatches' \
--header 'Accept: application/vnd.github.v3+json' \
--header 'Authorization: Basic ${{secrets.CF_GITHUB_WORKER_ENCODED_BASIC_AUTH}}' \
--header 'Authorization: Basic ${{env.CF_GITHUB_WORKER_ENCODED_BASIC_AUTH}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"event_type": "${{env.EVENT_TYPE}}",
Expand Down
1 change: 1 addition & 0 deletions sdk/typescript/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
plugins: ['unused-imports'],
rules: {
'@typescript-eslint/explicit-member-accessibility': 'off',
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
'arrow-body-style': ['error', 'as-needed'],
'no-undef': 'off',
Expand Down
102 changes: 89 additions & 13 deletions sdk/typescript/README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,101 @@
# Gateway API SDK

This SDK is a thin wrapper around the [Babylon Gateway API](https://docs-babylon.radixdlt.com/main/apis/api-specification.html).
This SDK is a thin wrapper around the [Babylon Gateway API](https://docs-babylon.radixdlt.com/main/apis/api-specification.html). It enables clients to efficiently query current and historic state on the RadixDLT ledger, and intelligently handle transaction submission. It is designed for use by wallets and explorers. For simple use cases, you can typically use the [Core API](https://github.com/radixdlt/babylon-node/tree/main/sdk/typescript) on a Node. A Gateway is only needed for reading historic snapshots of ledger states or a more robust set-up.

## Usage
## Structure

Behind the scenes, this library uses the fetch API.
There are four sub APIs available in the Gateway API:

If in an environment where `fetch` is not available, a polyfill must be used (see eg [node-fetch](https://www.npmjs.com/package/node-fetch)).
- Status - For status and configuration details for the Gateway / Network.
- Transaction - For transaction construction, preview, submission, and monitoring the status of an individual transaction.
- Stream - For reading committed transactions.
- State - For reading the current or past ledger state of the network.

All APIs generated from OpenAPI specification are available after initialization through `innerClient` object on corresponding sub-api. See examples in [Low Level APIs section](#low-level-apis). On top of that, this package provides [high-level counterparts](#high-level-apis) for each sub api.

## Versioning

All developers looking for an RCnet V1 compatible API should install versions which have `-rc.1.X` suffix. We'll be publishing internal versions with different suffixes which might not work well with publicly available network. All availble versions are published to [NPM repository](https://www.npmjs.com/package/@radixdlt/babylon-gateway-api-sdk?activeTab=versions)

## Initialization

Calling static `intialize` method from `GatewayApiClient` class will instantiate all low-level APIs together with their high-level equivalents and return them as a single object.

```typescript
import "./node-fetch-polyfill" // Polyfill for fetch required if running in node-js
import { StateApi, StatusApi, TransactionApi, StreamApi } from "@radixdlt/babylon-gateway-api-sdk";
import { GatewayApiClient } from '@radixdlt/babylon-gateway-api-sdk'

const gatewayApi = GatewayApiClient.initialize({
basePath: 'https://rcnet.radixdlt.com',
})
const { status, transaction, stream, state } = gatewayApi
```

## Low Level APIs

const transactionApi = new TransactionApi();
Low level APIs are generated automatically based on OpenAPI spec. You can get a good sense of available methods by looking at [Swagger](https://rcnet.radixdlt.com/swagger/index.html). In order to access automatically generated methods you have two options:

### Using generated APIs through `innerClient`

```typescript
async function getTransactionStatus(transactionIntentHashHex: string) {
let response = await transactionApi.transactionStatus({
transactionStatusRequest: {
intent_hash_hex: transactionIntentHashHex
}
});
return response.status;
let response = await gatewayApi.transaction.innerClient.transactionStatus({
transactionStatusRequest: {
intent_hash_hex: transactionIntentHashHex,
},
})
return response.status
}
console.log(await getTransactionStatus('266cdfe0a28a761909d04761cdbfe33555ee5fdcf1db37fcf71c9a644b53e60b'))
```

### Using generated APIs manually

You can always opt-out of using aggregated gateway client and instantiate sub-apis manually

```typescript
import { Configuration, StateApi } from '@radixdlt/babylon-gateway-api-sdk'
const config = new Configuration({ basePath: CURRENT_NETWORK?.url })
const stateApi = new StateApi(config)
const response = await stateApi.nonFungibleData({
stateNonFungibleDataRequest: {
resource_address: address,
non_fungible_ids: [id]
}
})
console.log(response.non_fungible_ids)
```

## High Level APIs

High Level APIs will grow over time as we start encountering repeating patterns when dealing with low level APIs. They are supposed to help with most commonly performed tasks and standardize ways of working with Gateway API and Typescript.

### State

- `getEntityDetailsVaultAggregated(entities: string | string[])` - detailed information about entities

### Status

- `getCurrent()` - Gateway API version and current ledger state
- `getNetworkConfiguration()` - network identifier, network name and well-known network addresses

### Transaction

- `getStatus(txID: string)` - transaction status for given transaction id (the intent hash)
- `getCommittedDetails(txID: string)` - transaction details together with ledger state at a time of commit for given transaction id (the intent hash)

## Fetch polyfill

Behind the scenes, this library uses the fetch API. If in an environment where `fetch` is not available, a polyfill must be used (see eg [node-fetch](https://www.npmjs.com/package/node-fetch)). Pass your own `fetch` implementation to [`initialize` parameter](https://github.com/radixdlt/babylon-gateway/blob/develop/sdk/typescript/lib/generated/runtime.ts#L20).

Starting from NodeJS 16 `fetch` is available as experimental API. You can e.g. check Gateway API status by using following snippet.

```typescript
const { GatewayApiClient } = require('@radixdlt/babylon-gateway-api-sdk')

const gateway = GatewayApiClient.initialize({
basePath: 'https://rcnet.radixdlt.com',
})
gateway.status.getCurrent().then(console.log)
```

Save this as `index.js` and use by calling `node --experimental-fetch index.js`. This will enable experimental fetch and let code work without additional configuration. In NodeJS 18.x environment fetch API is enabled by default. Users of previous node versions will need to provide their own `fetch` implementation through configuration object.
54 changes: 53 additions & 1 deletion sdk/typescript/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,53 @@
export * from "./generated"
import { StreamApi } from './generated/apis/StreamApi'
import {
Configuration,
ConfigurationParameters,
StateApi,
StatusApi,
TransactionApi,
} from './generated'
import { State } from './subapis/state'
import { Status, Stream } from './subapis'
import { Transaction } from './subapis/transaction'

export * from './generated'
export * from './subapis'

export type GatewayApiClientSettings = ConfigurationParameters

export class GatewayApiClient {
static initialize(settings?: GatewayApiClientSettings) {
const configuration = GatewayApiClient.constructConfiguration(settings)
return new GatewayApiClient(configuration)
}

private static constructConfiguration(settings?: GatewayApiClientSettings) {
return new Configuration(settings)
}

state: State
stream: Stream
status: Status
transaction: Transaction

private lowLevel: {
state: StateApi
stream: StreamApi
status: StatusApi
transaction: TransactionApi
}

constructor(configuration: Configuration) {
this.lowLevel = {
state: new StateApi(configuration),
stream: new StreamApi(configuration),
status: new StatusApi(configuration),
transaction: new TransactionApi(configuration),
}

this.state = new State(this.lowLevel.state)
this.stream = new Stream(this.lowLevel.stream)
this.status = new Status(this.lowLevel.status)
this.transaction = new Transaction(this.lowLevel.transaction)
}
}
4 changes: 4 additions & 0 deletions sdk/typescript/lib/subapis/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './state'
export * from './status'
export * from './stream'
export * from './transaction'
65 changes: 65 additions & 0 deletions sdk/typescript/lib/subapis/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
FungibleResourcesCollection,
FungibleResourcesCollectionItemVaultAggregated,
NonFungibleResourcesCollection,
NonFungibleResourcesCollectionItemVaultAggregated,
ResourceAggregationLevel,
StateApi,
StateEntityDetailsResponseItem,
} from '../generated'

type ReplaceItems<T, U> = Omit<T, 'items'> & { items: U[] }

export type FungibleResourcesVaultCollection = ReplaceItems<
FungibleResourcesCollection,
FungibleResourcesCollectionItemVaultAggregated
>
export type NonFungibleResourcesVaultCollection = ReplaceItems<
NonFungibleResourcesCollection,
NonFungibleResourcesCollectionItemVaultAggregated
>

export type StateEntityDetailsVaultResponseItem =
StateEntityDetailsResponseItem & {
fungible_resources: FungibleResourcesVaultCollection
non_fungible_resources: NonFungibleResourcesVaultCollection
}

export class State {
constructor(public innerClient: StateApi) {}

/**
* Get detailed information about entities together with vault aggregated fungible and non-fungible resources.
* Returns array or single item depending on input value
*
* @example
* const entityDetails = await gatewayApi.state.getEntityDetailsVaultAggregated('account_tdx_21_1p823h2sq7nsefkdharvvh5')
* console.log(entityDetails.fungible_resources.items, entityDetails.non_fungible_resources.items)
*
* @example
* const entities = await gatewayApi.state.getEntityDetailsVaultAggregated(['account_tdx_21_1p823h2sq7nsefkdharvvh5'])
* console.log(entities[0].fungible_resources.items, entities[0].non_fungible_resources.items)
*/
async getEntityDetailsVaultAggregated(
addresses: string
): Promise<StateEntityDetailsVaultResponseItem>
async getEntityDetailsVaultAggregated(
addresses: string[]
): Promise<StateEntityDetailsVaultResponseItem[]>
async getEntityDetailsVaultAggregated(
addresses: string[] | string
): Promise<
StateEntityDetailsVaultResponseItem[] | StateEntityDetailsVaultResponseItem
> {
const isArray = Array.isArray(addresses)
const { items } = await this.innerClient.stateEntityDetails({
stateEntityDetailsRequest: {
addresses: isArray ? addresses : [addresses],
aggregation_level: ResourceAggregationLevel.Vault,
},
})
return isArray
? (items as StateEntityDetailsVaultResponseItem[])
: (items[0] as StateEntityDetailsVaultResponseItem)
}
}
19 changes: 19 additions & 0 deletions sdk/typescript/lib/subapis/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { GatewayStatusResponse, NetworkConfigurationResponse, StatusApi } from "../generated";

export class Status {
constructor(public innerClient: StatusApi) {}

/**
* Get Gateway API version and current ledger state
*/
getCurrent(): Promise<GatewayStatusResponse> {
return this.innerClient.gatewayStatus()
}

/**
* Get network identifier, network name and well-known network addresses
*/
getNetworkConfiguration(): Promise<NetworkConfigurationResponse> {
return this.innerClient.networkConfiguration()
}
}
6 changes: 6 additions & 0 deletions sdk/typescript/lib/subapis/stream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { StreamApi } from "../generated";

export class Stream {
constructor(public innerClient: StreamApi) {
}
}
Loading

0 comments on commit 4586d93

Please sign in to comment.