Skip to content

Pull oracles #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/Developers/Guides/Chronicle Pull Oracles/GettingStarted.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
sidebar_position: 1
description: Developer documentation for Chronicle's Pull Oracle
keywords: [pull oracle]
---
# Getting Started

Chronicle's pull oracles offer the absolute freshest pricing information on-demand. We provide an [NPM package](https://www.npmjs.com/package/@chronicleprotocol/pull-oracle) for simple integrations. Authentication is handled via tokens based on the [Ethereum Signed Messages](https://eips.ethereum.org/EIPS/eip-191) protocol.

:::info
Your public signing key must be allow-listed on our servers before your tokens will be accepted as valid.
:::

### Generating authentication tokens on the server:
```js
import { signAuthToken } from '@chronicleprotocol/pull-oracle';

const { token, message } = await signAuthToken({
// private key is 0x prefixed 32 byte hex string
privateKey: "0xabc..."
})
```

:::warning
We highly recommend following best practices for private key generation and storage. Use a unique private key for creating auth tokens. DO NOT re-use this private key for any other purpose!
:::

Once the auth token is generated on the server, pass it to the client and register it with the `authenticate` method of the `pull-oracle` module for automatic inclusion in future requests.

### Authenticating a user session on the client and fetching prices:
```js
import { authenticate, getPrices } from '@chronicleprotocol/pull-oracle';

// token is received from the server
// `authenticate` caches the token in memory so it only needs to be called once per session
authenticate(token);

const prices = await getPrices([
{ wat: "MKR/USD", blockchain: "ETH" },
{ wat: "ETH/USD", blockchain: "ETH" }
]);
```
228 changes: 228 additions & 0 deletions docs/Developers/Guides/Chronicle Pull Oracles/Types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
---
sidebar_position: 6
description: Pull Oracle - Types
keywords: [pull oracle]
---
# Types & Constants

## Types

### `APIResponseError`

Occurs when there is an error processing the request.

```ts
interface APIResponseError {
error: true;
data?: any;
message: string;
code: AuthTokenCode | APIErrorCode;
}
```

---

### `AuthTokenMessage`

The message returned from [`signAuthToken`](./authenticate.md#signauthtoken).

```ts
type AuthTokenMessage {
description: string;
version: number;
validFrom: number;
validTo: number;
signer: Address;
nonce: number;
}
```

- `description`: the description of the token, e.g. "Chronicle API token"
- `version`: the authentication API version number
- `validFrom`: unix epoch timestamp starting from then the token is valid, inclusive
- `validTo`: unix epoch timestamp until when the auth token is valid, inclusive
- `signer`: the address of the signer
- `nonce`: unique number


---

### `Blockchain`

A blockchain identifier of either the `shortName` or `chainId` per [chainid.network](https://chainid.network/chains.json).

```ts
type Blockchain = string | number;
```

---

### `PairData`

The data structure returned from [`getPairs`](./getPairs.md)

```ts
type PairData = {
scheme: Scheme;
blockchain: Blockchain;
pairs: Pairs;
}
```

---

### `Pairs`

The data structure containing pairs.

```ts
type Pairs = Record<string, { bar: number; validators: Address[] }>;
```

Example:
```ts
{
"BTC/USD": {
bar: 13,
validators: [
"0xabc123...",
"0xabc123...",
"0xabc123...",
...
]
}
}
```

---

### `PriceData`

The data structure returned from [`getPrices`](./getPrices.md)

```ts
type PriceData = {
wat: string;
scheme: Scheme;
bar: number;
messages: PriceMessage[];
}
```

---

### `PriceMessage`

The data structure of an individual price message. A batch of price messages makes up a single oracle price.

```ts
type PriceMessage {
wat: string;
val: string;
age: number;
r: string;
s: string;
v: string;
}
```

---

### `PriceRequest`

The data structure of the argument passed to [`getPrices`](./getPrices.md)

```ts
type PriceRequest {
wat: string;
scheme?: Scheme;
}
```

---

### `ValidatorData`

The data structure returned from [`getPairs`](./getPairs.md)

```ts
type ValidatorData {
scheme: Scheme;
validators: Validator[];
}
```

---

## Constants

:::info
Note: all enum values are identical to their keys, but only keys are shown here for simplicity
:::


### `Scheme`

Encryption scheme for price messages. Currently there is only one option, however more options may be offered in the future.

```ts
enum Scheme {
ECDSA
}
```
- `ECDSA`: Price messages are signed with [Elliptic Curve Digital Signature Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) encryption.

---

### `AuthTokenCodes`

Response codes for auth token verification.

```ts
enum AuthTokenCode {
VALID,
EXPIRED,
NOT_YET_VALID,
DURATION_EXCEEDS_MAX,
INVALID_SIGNATURE,
INVALID_VERSION,
MALFORMED_TOKEN,
SIGNER_NOT_AUTHORIZED
}
```

- `VALID`: Auth token is valid
- `EXPIRED`: Auth token end time has passed
- `NOT_YET_VALID`: Auth token start time has not yet occurred
- `DURATION_EXCEEDS_MAX`: The period between auth token start and end times is too long
- `INVALID_SIGNATURE`: The auth token `signer` field and recovered signature do not match
- `INVALID_VERSION`: The auth token is using an unrecognized version
- `MALFORMED_TOKEN`: The auth token has some other error not covered by the other codes
- `SIGNER_NOT_AUTHORIZED`: The token signer is not authorized by Chronicle

---

### `APIErrorCode`

Response codes for API errors.

```ts
enum APIErrorCode {
FAILED_REQUEST,
SCHEME_NOT_SUPPORTED,
BLOCKCHAIN_NOT_SUPPORTED,
PAIR_NOT_SUPPORTED,
MISSING_REQUIRED_PARAMETER,
METHOD_NOT_ALLOWED,
INVALID_REQUEST_DATA,
}
```

- `FAILED_REQUEST`: The API request failed to receive a valid response from the server
- `SCHEME_NOT_SUPPORTED`: The API request was made for a [Scheme](#scheme) that is not supported
- `BLOCKCHAIN_NOT_SUPPORTED`: The API request was made for a [Blockchain](#blockchain) that is not supported
- `PAIR_NOT_SUPPORTED`: The API request was made for a [Pair](#pair) that is not supported
- `MISSING_REQUIRED_PARAMETER`: The API request was missing a required parameter and was therefore unable to complete
- `METHOD_NOT_ALLOWED`: The HTTP method used to access the API is not allowed
- `INVALID_REQUEST_DATA`: The request data was not parseable or inadequate to complete the request

91 changes: 91 additions & 0 deletions docs/Developers/Guides/Chronicle Pull Oracles/authenticate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
sidebar_position: 2
description: Pull Oracle - authenticate
keywords: [pull oracle]
---

# Authentication

## `signAuthToken`

A server-side function which creates an auth token to be used to [authenticate](#authenticate) [getPrices](./getPrices.md) requests.

### Usage

Generating authentication tokens on the server:
```js
import { signAuthToken } from '@chronicleprotocol/pull-oracle';

const { token, message } = await signAuthToken({
// private key is 0x prefixed 32 byte hex string
privateKey: "0xabc..."
})
```

### Returns

```js
{
token: "...",
message: AuthTokenMessage
}
```

### Parameters

```ts
{ privateKey: "0xabc...", duration: 1800 }
```

#### `privateKey`

- Type: `string`

The `privateKey` for the account signing the auth token.

#### `duration`

- _Optional_
- Default: 1800
- Type: `number`

The duration of validity for the auth token in seconds.

---

## `authenticate`

A client-side function which validates and caches the auth token which was received from the server for future use with [getPrices](./getPrices.md).

### Usage

```js
import { authenticate } from '@chronicleprotocol/pull-oracle';

// token is received from the server
// `authenticate` caches the token in memory so it only needs to be called once per session
authenticate(token);
```

### Returns

- `boolean`: whether the provided auth token is _currently_ valid.

---

# `isAuthenticated`

A function to check whether the library has a currently valid auth token previously cached by the [authenticate](#authenticate) function.

### Usage

```js
import { isAuthenticated } from '@chronicleprotocol/pull-oracle';

// token from the cache is verified
const isAuthenticated = isAuthenticated()
```

### Returns

- `boolean`: whether the cached auth token is _currently_ valid.
Loading