mirror of
https://github.com/logos-storage/logos-storage-js.git
synced 2026-01-07 16:03:06 +00:00
Generate types from the open api file
This commit is contained in:
parent
746f96279b
commit
4750e0b6fe
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
*.tgz
|
*.tgz
|
||||||
|
index.bundle.js
|
||||||
86
README.md
86
README.md
@ -10,6 +10,14 @@ The SDK is currently under early development and the API can change at any time.
|
|||||||
|
|
||||||
- Version 0.1.0 introduces [upload strategy](#upload) to support browser and Node JS.
|
- Version 0.1.0 introduces [upload strategy](#upload) to support browser and Node JS.
|
||||||
|
|
||||||
|
## Types generation
|
||||||
|
|
||||||
|
The types are generated from the openapi.yaml using the commande:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx openapi-typescript ./openapi.yaml -o src/openapi.ts --default-non-nullable false
|
||||||
|
```
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
### Sync api
|
### Sync api
|
||||||
@ -105,14 +113,14 @@ const codex = new Codex("http://localhost:3000");
|
|||||||
const marketplace = await codex.marketplace();
|
const marketplace = await codex.marketplace();
|
||||||
|
|
||||||
// When using the sync api
|
// When using the sync api
|
||||||
const marketplace = codex.marketplace
|
const marketplace = codex.marketplace;
|
||||||
```
|
```
|
||||||
|
|
||||||
#### activeSlots()
|
#### activeSlots()
|
||||||
|
|
||||||
Returns active slots.
|
Returns active slots.
|
||||||
|
|
||||||
- returns Promise<[CodexSlot](./src/marketplace/types.ts#L85)[]>
|
- returns Promise<[CodexSlot](./src/marketplace/types.ts#L7)[]>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -125,7 +133,7 @@ const slots = await marketplace.activeSlots();
|
|||||||
Returns active slot with id {slotId} for the host.
|
Returns active slot with id {slotId} for the host.
|
||||||
|
|
||||||
- slotId (string, required)
|
- slotId (string, required)
|
||||||
- returns Promise<[CodexSlot](./src/marketplace/types.ts#L85)[]>
|
- returns Promise<[CodexSlotAgent](./src/marketplace/types.ts#L12)[]>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -138,7 +146,7 @@ const slot = await marketplace.activeSlot(slotId);
|
|||||||
|
|
||||||
Returns storage that is for sale.
|
Returns storage that is for sale.
|
||||||
|
|
||||||
- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L99)>
|
- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L20)>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -150,8 +158,8 @@ const availabilities = await marketplace.availabilities();
|
|||||||
|
|
||||||
Offers storage for sale.
|
Offers storage for sale.
|
||||||
|
|
||||||
- input ([CodexCreateAvailabilityInput](./src/marketplace/types.ts#L175), required)
|
- input ([CodexCreateAvailabilityInput](./src/marketplace/types.ts#L45), required)
|
||||||
- returns Promise<[CodexAvailabilityCreateResponse](./src/marketplace/types.ts#L186)[]>
|
- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L20)[]>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -168,7 +176,7 @@ const response = await marketplace.createAvailability({
|
|||||||
|
|
||||||
Updates availability.
|
Updates availability.
|
||||||
|
|
||||||
- input ([CodexUpdateAvailabilityInput](./src/marketplace/types.ts#L186), required)
|
- input ([CodexAvailabilityPatchInput](./src/marketplace/types.ts#L66), required)
|
||||||
- returns Promise<"">
|
- returns Promise<"">
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -188,7 +196,7 @@ const response = await marketplace.updateAvailability({
|
|||||||
Return list of reservations for ongoing Storage Requests that the node hosts.
|
Return list of reservations for ongoing Storage Requests that the node hosts.
|
||||||
|
|
||||||
- availabilityId (string, required)
|
- availabilityId (string, required)
|
||||||
- returns Promise<[CodexReservation](./src/marketplace/types.ts#L198)[]>
|
- returns Promise<[CodexReservation](./src/marketplace/types.ts#L83)[]>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -200,7 +208,7 @@ const reservations = await marketplace.reservations("Ox...");
|
|||||||
|
|
||||||
Creates a new Request for storage
|
Creates a new Request for storage
|
||||||
|
|
||||||
- input ([CodexCreateStorageRequestInput](./src/marketplace/types.ts#L230), required)
|
- input ([CodexCreateStorageRequestInput](./src/marketplace/types.ts#L120), required)
|
||||||
- returns Promise<string>
|
- returns Promise<string>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -234,7 +242,7 @@ const ids = await marketplace.purchaseIds();
|
|||||||
Returns purchase details
|
Returns purchase details
|
||||||
|
|
||||||
- purchaseId (string, required)
|
- purchaseId (string, required)
|
||||||
- returns Promise<[CodexPurchase](./src/marketplace/types.ts#L214)[]>
|
- returns Promise<[CodexPurchase](./src/marketplace/types.ts#L103)[]>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -253,14 +261,14 @@ const codex = new Codex("http://localhost:3000");
|
|||||||
const data = await codex.data();
|
const data = await codex.data();
|
||||||
|
|
||||||
// When using the sync api
|
// When using the sync api
|
||||||
const data = codex.data
|
const data = codex.data;
|
||||||
```
|
```
|
||||||
|
|
||||||
#### cids
|
#### cids
|
||||||
|
|
||||||
Returns the manifest stored locally in node.
|
Returns the manifest stored locally in node.
|
||||||
|
|
||||||
- returns Promise<[CodexDataResponse](./src/data/types.ts#L54)[]>
|
- returns Promise<[CodexDataItem](./src/data/types.ts#L7)[]>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -272,7 +280,7 @@ const cids = await data.cids();
|
|||||||
|
|
||||||
Returns a summary of the storage space allocation of the node
|
Returns a summary of the storage space allocation of the node
|
||||||
|
|
||||||
- returns Promise<[CodexNodeSpace](./src/data/types.ts#L56)[]>
|
- returns Promise<[CodexNodeSpace](./src/data/types.ts#L14)[]>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -287,7 +295,7 @@ Upload a file in a streaming manner
|
|||||||
#### Browser
|
#### Browser
|
||||||
|
|
||||||
- stategy [BrowserUploadStategy](./src/data/browser-upload.ts#L5)
|
- stategy [BrowserUploadStategy](./src/data/browser-upload.ts#L5)
|
||||||
- returns [UploadResponse](./src/data/types.ts#L80)
|
- returns [UploadResponse](./src/data/types.ts#L16)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -316,8 +324,8 @@ console.info("CID is", res.data);
|
|||||||
|
|
||||||
#### Node
|
#### Node
|
||||||
|
|
||||||
- stategy [NodeUploadStategy](./src/data/node-download.ts#L8)
|
- stategy [NodeUploadStategy](./src/data/node-upload.ts#L8)
|
||||||
- returns [UploadResponse](./src/data/types.ts#L80)
|
- returns [UploadResponse](./src/data/types.ts#L16)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -340,7 +348,7 @@ console.info("CID is", res.data);
|
|||||||
Download only the dataset manifest from the network to the local node if it's not available locally.
|
Download only the dataset manifest from the network to the local node if it's not available locally.
|
||||||
|
|
||||||
- cid (string, required)
|
- cid (string, required)
|
||||||
- returns [CodexManifest](./src/data/types.ts#L3)
|
- returns [CodexManifest](./src/data/types.ts#L29)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -389,14 +397,14 @@ const codex = new Codex("http://localhost:3000");
|
|||||||
const data = await codex.debug();
|
const data = await codex.debug();
|
||||||
|
|
||||||
// When using the sync api
|
// When using the sync api
|
||||||
const data = codex.debug
|
const data = codex.debug;
|
||||||
```
|
```
|
||||||
|
|
||||||
#### setLogLevel
|
#### setLogLevel
|
||||||
|
|
||||||
Set log level at run time.
|
Set log level at run time.
|
||||||
|
|
||||||
- level ([CodexLogLevel](./src/debug/types.ts#L3), required)
|
- level ([CodexLogLevel](./src/debug/types.ts#L7), required)
|
||||||
- returns Promise<"">
|
- returns Promise<"">
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -409,7 +417,7 @@ await debug.setLogLevel("DEBUG");
|
|||||||
|
|
||||||
Gets node information
|
Gets node information
|
||||||
|
|
||||||
- returns Promise<[CodexDebugInfo](./src/debug/types.ts#L15)>
|
- returns Promise<[CodexDebugInfo](./src/debug/types.ts#L23)>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -427,17 +435,51 @@ const codex = new Codex("http://localhost:3000");
|
|||||||
const node = await codex.node();
|
const node = await codex.node();
|
||||||
|
|
||||||
// When using the sync api
|
// When using the sync api
|
||||||
const node = codex.node
|
const node = codex.node;
|
||||||
```
|
```
|
||||||
|
|
||||||
#### spr
|
#### spr
|
||||||
|
|
||||||
Get Node's SPR
|
Get Node's SPR
|
||||||
|
|
||||||
- returns Promise<[CodexSpr](./src/node/types.ts#L1)>
|
- returns Promise<[CodexSpr](./src/node/types.ts#L11)>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const spr = await node.spr();
|
const spr = await node.spr();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, the response will be a json. You can use `text` option to get the string:
|
||||||
|
|
||||||
|
#### peeriD
|
||||||
|
|
||||||
|
Get Node's peer id
|
||||||
|
|
||||||
|
- returns Promise<[CodexPeerId](./src/node/types.ts#L25)>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const peerId = await node.peerId();
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the response will be a json. You can use `text` option to get the string:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const peerId = await node.peerId("text");
|
||||||
|
```
|
||||||
|
|
||||||
|
#### connect
|
||||||
|
|
||||||
|
Connect to a peer
|
||||||
|
|
||||||
|
- returns Promise<string>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const peerId = "..."
|
||||||
|
const addrs = [...]
|
||||||
|
const spr = await node.connect(peerId, addrs);
|
||||||
|
```
|
||||||
|
|||||||
1005
openapi.yaml
Normal file
1005
openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
1110
package-lock.json
generated
1110
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@codex-storage/sdk-js",
|
"name": "@codex-storage/sdk-js",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"description": "Codex SDK to interact with the Codex decentralized storage network.",
|
"description": "Codex SDK to interact with the Codex decentralized storage network.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -78,6 +78,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tsconfig/strictest": "^2.0.5",
|
"@tsconfig/strictest": "^2.0.5",
|
||||||
"@types/node": "^22.13.13",
|
"@types/node": "^22.13.13",
|
||||||
|
"oas-normalize": "^13.1.2",
|
||||||
|
"openapi-typescript": "^7.6.1",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"tsup": "^8.3.6",
|
"tsup": "^8.3.6",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
|
|||||||
@ -3,11 +3,14 @@ import { Fetch } from "../fetch-safe/fetch-safe";
|
|||||||
import type { SafeValue } from "../values/values";
|
import type { SafeValue } from "../values/values";
|
||||||
import type {
|
import type {
|
||||||
CodexDataResponse,
|
CodexDataResponse,
|
||||||
CodexManifest,
|
|
||||||
CodexNodeSpace,
|
|
||||||
UploadStategy,
|
UploadStategy,
|
||||||
NetworkDownloadResponse,
|
|
||||||
UploadResponse,
|
UploadResponse,
|
||||||
|
CodexSpaceResponse,
|
||||||
|
CodexNodeSpace,
|
||||||
|
CodexDataNetworkResponse,
|
||||||
|
CodexNetworkDownload,
|
||||||
|
CodexManifest,
|
||||||
|
CodexDataItems,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export class CodexData {
|
export class CodexData {
|
||||||
@ -21,27 +24,19 @@ export class CodexData {
|
|||||||
* Lists manifest CIDs stored locally in node.
|
* Lists manifest CIDs stored locally in node.
|
||||||
* TODO: remove the faker data part when the api is ready
|
* TODO: remove the faker data part when the api is ready
|
||||||
*/
|
*/
|
||||||
cids(): Promise<SafeValue<CodexDataResponse>> {
|
cids(): Promise<SafeValue<CodexDataItems>> {
|
||||||
const url = this.url + Api.config.prefix + "/data";
|
const url = this.url + Api.config.prefix + "/data";
|
||||||
|
|
||||||
return Fetch.safeJson<CodexDataResponse>(url, { method: "GET" }).then(
|
return Fetch.safeJson<CodexDataResponse>(url, { method: "GET" });
|
||||||
(data) => {
|
|
||||||
if (data.error) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { error: false, data: { content: data.data.content } };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a summary of the storage space allocation of the node.
|
* Gets a summary of the storage space allocation of the node.
|
||||||
*/
|
*/
|
||||||
space() {
|
space(): Promise<SafeValue<CodexNodeSpace>> {
|
||||||
const url = this.url + Api.config.prefix + "/space";
|
const url = this.url + Api.config.prefix + "/space";
|
||||||
|
|
||||||
return Fetch.safeJson<CodexNodeSpace>(url, { method: "GET" });
|
return Fetch.safeJson<CodexSpaceResponse>(url, { method: "GET" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,12 +70,10 @@ export class CodexData {
|
|||||||
* Download a file from the network to the local node if it's not available locally.
|
* Download a file from the network to the local node if it's not available locally.
|
||||||
* Note: Download is performed async. Call can return before download is completed.
|
* Note: Download is performed async. Call can return before download is completed.
|
||||||
*/
|
*/
|
||||||
async networkDownload(
|
async networkDownload(cid: string): Promise<SafeValue<CodexNetworkDownload>> {
|
||||||
cid: string
|
|
||||||
): Promise<SafeValue<NetworkDownloadResponse>> {
|
|
||||||
const url = this.url + Api.config.prefix + `/data/${cid}/network`;
|
const url = this.url + Api.config.prefix + `/data/${cid}/network`;
|
||||||
|
|
||||||
return Fetch.safeJson(url, { method: "POST" });
|
return Fetch.safeJson<CodexDataNetworkResponse>(url, { method: "POST" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,7 +90,7 @@ export class CodexData {
|
|||||||
* Download only the dataset manifest from the network to the local node
|
* Download only the dataset manifest from the network to the local node
|
||||||
* if it's not available locally.
|
* if it's not available locally.
|
||||||
*/
|
*/
|
||||||
async fetchManifest(cid: string) {
|
async fetchManifest(cid: string): Promise<SafeValue<CodexManifest>> {
|
||||||
const url = this.url + Api.config.prefix + `/data/${cid}/network/manifest`;
|
const url = this.url + Api.config.prefix + `/data/${cid}/network/manifest`;
|
||||||
|
|
||||||
return Fetch.safeJson<CodexManifest>(url, { method: "GET" });
|
return Fetch.safeJson<CodexManifest>(url, { method: "GET" });
|
||||||
|
|||||||
@ -1,86 +1,32 @@
|
|||||||
|
import type { components, paths } from "../openapi";
|
||||||
import type { SafeValue } from "../values/values";
|
import type { SafeValue } from "../values/values";
|
||||||
|
|
||||||
export type CodexManifest = {
|
export type CodexDataResponse =
|
||||||
/**
|
paths["/data"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
* "Root hash of the content"
|
|
||||||
*/
|
|
||||||
// rootHash: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexDataItem = components["schemas"]["DataItem"];
|
||||||
* Length of original content in bytes
|
|
||||||
*/
|
|
||||||
// originalBytes: number;
|
|
||||||
|
|
||||||
/**
|
export type CodexDataItems = CodexDataResponse;
|
||||||
* Total size of all blocks
|
|
||||||
*/
|
|
||||||
datasetSize: number;
|
|
||||||
|
|
||||||
/**
|
export type CodexSpaceResponse =
|
||||||
* "Size of blocks"
|
paths["/space"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
*/
|
|
||||||
blockSize: number;
|
|
||||||
|
|
||||||
/**
|
export type CodexNodeSpace = CodexSpaceResponse;
|
||||||
* Indicates if content is protected by erasure-coding
|
|
||||||
*/
|
|
||||||
protected: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Root of the merkle tree
|
|
||||||
*/
|
|
||||||
treeCid: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the name
|
|
||||||
*/
|
|
||||||
filename: string | null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mimetype
|
|
||||||
*/
|
|
||||||
mimetype: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CodexDataContent = {
|
|
||||||
/**
|
|
||||||
* Content Identifier as specified at https://github.com/multiformats/cid
|
|
||||||
*/
|
|
||||||
cid: string;
|
|
||||||
|
|
||||||
manifest: CodexManifest;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CodexDataResponse = { content: CodexDataContent[] };
|
|
||||||
|
|
||||||
export type CodexNodeSpace = {
|
|
||||||
/**
|
|
||||||
* Number of blocks stored by the node
|
|
||||||
*/
|
|
||||||
totalBlocks: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum storage space used by the node
|
|
||||||
*/
|
|
||||||
quotaMaxBytes: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount of storage space currently in use
|
|
||||||
*/
|
|
||||||
quotaUsedBytes: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount of storage space reserved
|
|
||||||
*/
|
|
||||||
quotaReservedBytes: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UploadResponse = {
|
export type UploadResponse = {
|
||||||
result: Promise<SafeValue<string>>;
|
result: Promise<SafeValue<string>>;
|
||||||
abort: () => void;
|
abort: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NetworkDownloadResponse = { cid: string; manifest: CodexManifest };
|
export type CodexDataNetworkResponse =
|
||||||
|
paths["/data/{cid}/network"]["post"]["responses"][200]["content"]["application/json"];
|
||||||
|
|
||||||
|
export type CodexNetworkDownload = components["schemas"]["DataItem"];
|
||||||
|
|
||||||
|
export type CodexFetchManifestResponse =
|
||||||
|
paths["/data/{cid}/network/manifest"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
|
|
||||||
|
export type CodexManifest = CodexFetchManifestResponse;
|
||||||
|
|
||||||
export interface UploadStategy {
|
export interface UploadStategy {
|
||||||
download(url: string): Promise<SafeValue<string>>;
|
download(url: string): Promise<SafeValue<string>>;
|
||||||
|
|||||||
@ -2,7 +2,12 @@ import { Api } from "../api/config";
|
|||||||
import { CodexError, CodexValibotIssuesMap } from "../errors/errors";
|
import { CodexError, CodexValibotIssuesMap } from "../errors/errors";
|
||||||
import { Fetch } from "../fetch-safe/fetch-safe";
|
import { Fetch } from "../fetch-safe/fetch-safe";
|
||||||
import type { SafeValue } from "../values/values";
|
import type { SafeValue } from "../values/values";
|
||||||
import { CodexLogLevel, type CodexDebugInfo } from "./types";
|
import {
|
||||||
|
CodexLogLevelInput,
|
||||||
|
type CodexDebugInfo,
|
||||||
|
type CodexInfoResponse,
|
||||||
|
type CodexLogLevel,
|
||||||
|
} from "./types";
|
||||||
import * as v from "valibot";
|
import * as v from "valibot";
|
||||||
|
|
||||||
export class CodexDebug {
|
export class CodexDebug {
|
||||||
@ -15,8 +20,8 @@ export class CodexDebug {
|
|||||||
/**
|
/**
|
||||||
* Set log level at run time
|
* Set log level at run time
|
||||||
*/
|
*/
|
||||||
async setLogLevel(level: CodexLogLevel): Promise<SafeValue<"">> {
|
async setLogLevel(level: CodexLogLevel): Promise<SafeValue<string>> {
|
||||||
const result = v.safeParse(CodexLogLevel, level);
|
const result = v.safeParse(CodexLogLevelInput, level);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
@ -33,25 +38,19 @@ export class CodexDebug {
|
|||||||
"/debug/chronicles/loglevel?level=" +
|
"/debug/chronicles/loglevel?level=" +
|
||||||
level;
|
level;
|
||||||
|
|
||||||
const res = await Fetch.safe(url, {
|
return Fetch.safeText(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: "",
|
body: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.error) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { error: false, data: "" };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets node information
|
* Gets node information
|
||||||
*/
|
*/
|
||||||
info() {
|
info(): Promise<SafeValue<CodexDebugInfo>> {
|
||||||
const url = this.url + Api.config.prefix + `/debug/info`;
|
const url = this.url + Api.config.prefix + `/debug/info`;
|
||||||
|
|
||||||
return Fetch.safeJson<CodexDebugInfo>(url, {
|
return Fetch.safeJson<CodexInfoResponse>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
import * as v from "valibot";
|
import * as v from "valibot";
|
||||||
|
import type { paths } from "../openapi";
|
||||||
|
|
||||||
export const CodexLogLevel = v.picklist([
|
export type CodexLogLevelResponse =
|
||||||
|
paths["/debug/chronicles/loglevel"]["post"]["responses"][200]["content"];
|
||||||
|
|
||||||
|
export type CodexLogLevel =
|
||||||
|
paths["/debug/chronicles/loglevel"]["post"]["parameters"]["query"]["level"];
|
||||||
|
|
||||||
|
export const CodexLogLevelInput = v.picklist([
|
||||||
"TRACE",
|
"TRACE",
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
"INFO",
|
"INFO",
|
||||||
@ -10,49 +17,7 @@ export const CodexLogLevel = v.picklist([
|
|||||||
"FATAL",
|
"FATAL",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export type CodexLogLevel = v.InferOutput<typeof CodexLogLevel>;
|
export type CodexInfoResponse =
|
||||||
|
paths["/debug/info"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
|
|
||||||
export type CodexDebugInfo = {
|
export type CodexDebugInfo = CodexInfoResponse;
|
||||||
/**
|
|
||||||
* Peer Identity reference as specified at https://docs.libp2p.io/concepts/fundamentals/peers/
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address of node as specified by the multi-address specification https://multiformats.io/multiaddr/
|
|
||||||
*/
|
|
||||||
addrs: string[];
|
|
||||||
|
|
||||||
announceAddresses: string[]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path of the data repository where all nodes data are stored
|
|
||||||
*/
|
|
||||||
repo: string;
|
|
||||||
|
|
||||||
// Signed Peer Record (libp2p)
|
|
||||||
spr: string;
|
|
||||||
|
|
||||||
table: {
|
|
||||||
localNode: {
|
|
||||||
nodeId: string
|
|
||||||
peerId: string
|
|
||||||
record: string
|
|
||||||
address: string
|
|
||||||
seen: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes: {
|
|
||||||
nodeId: string
|
|
||||||
peerId: string
|
|
||||||
record: string
|
|
||||||
address: string
|
|
||||||
seen: boolean
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
|
|
||||||
codex: {
|
|
||||||
version: string
|
|
||||||
revision: string
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@ -45,4 +45,14 @@ export const Fetch = {
|
|||||||
|
|
||||||
return Promises.safe(() => res.data.json());
|
return Promises.safe(() => res.data.json());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async safeText(url: string, init: RequestInit): Promise<SafeValue<string>> {
|
||||||
|
const res = await this.safe(url, init);
|
||||||
|
|
||||||
|
if (res.error) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promises.safe(() => res.data.text());
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -104,10 +104,12 @@ function minNumberValidationError(field: string, min: number) {
|
|||||||
function createAvailability() {
|
function createAvailability() {
|
||||||
return {
|
return {
|
||||||
id: randomEthereumAddress(),
|
id: randomEthereumAddress(),
|
||||||
totalSize: randomInt(0, 9).toString(),
|
totalSize: randomInt(0, 9),
|
||||||
duration: randomInt(0, 9).toString(),
|
duration: randomInt(0, 9),
|
||||||
minPrice: randomInt(0, 9).toString(),
|
minPrice: randomInt(0, 9),
|
||||||
maxCollateral: randomInt(0, 9).toString(),
|
minPricePerBytePerSecond: randomInt(0, 9),
|
||||||
|
totalCollateral: randomInt(0, 900),
|
||||||
|
totalRemainingCollateral: randomInt(0, 900),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +212,7 @@ describe("marketplace", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("returns a response when the request succeed", async () => {
|
it("returns a response when the request succeed", async () => {
|
||||||
const data = { ...createAvailability(), freeSize: "1000" };
|
const data = { ...createAvailability(), freeSize: 1000 };
|
||||||
|
|
||||||
const spy = vi.spyOn(Fetch, "safeJson");
|
const spy = vi.spyOn(Fetch, "safeJson");
|
||||||
spy.mockImplementationOnce(() => Promise.resolve({ error: false, data }));
|
spy.mockImplementationOnce(() => Promise.resolve({ error: false, data }));
|
||||||
@ -228,16 +230,16 @@ describe("marketplace", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("returns a response when the create availability succeed", async () => {
|
it("returns a response when the create availability succeed", async () => {
|
||||||
const data = { ...createAvailability(), freeSize: "1000" };
|
const data = { ...createAvailability(), freeSize: 1000 };
|
||||||
|
|
||||||
const spy = vi.spyOn(Fetch, "safeJson");
|
const spy = vi.spyOn(Fetch, "safeJson");
|
||||||
spy.mockImplementationOnce(() => Promise.resolve({ error: false, data }));
|
spy.mockImplementationOnce(() => Promise.resolve({ error: false, data }));
|
||||||
|
|
||||||
const response = await marketplace.createAvailability({
|
const response = await marketplace.createAvailability({
|
||||||
totalCollateral: 1,
|
totalCollateral: data.totalCollateral,
|
||||||
totalSize: 3000,
|
totalSize: data.totalSize,
|
||||||
minPricePerBytePerSecond: 100,
|
minPricePerBytePerSecond: data.minPricePerBytePerSecond,
|
||||||
duration: 100,
|
duration: data.duration,
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.ok(!response.error);
|
assert.ok(!response.error);
|
||||||
|
|||||||
@ -4,16 +4,27 @@ import { CodexError, CodexValibotIssuesMap } from "../errors/errors";
|
|||||||
import { Fetch } from "../fetch-safe/fetch-safe";
|
import { Fetch } from "../fetch-safe/fetch-safe";
|
||||||
import type { SafeValue } from "../values/values";
|
import type { SafeValue } from "../values/values";
|
||||||
import {
|
import {
|
||||||
|
type CodexAvailabilityResponse,
|
||||||
type CodexAvailability,
|
type CodexAvailability,
|
||||||
|
type CodexSlot,
|
||||||
|
type CodexSlotAgent,
|
||||||
|
type CodexSlotResponse,
|
||||||
|
type CodexSlotAgentResponse,
|
||||||
|
type CodexAvailabilityWithoutTypes,
|
||||||
type CodexAvailabilityCreateResponse,
|
type CodexAvailabilityCreateResponse,
|
||||||
type CodexAvailabilityDto,
|
type CodexAvailabilityCreateBody,
|
||||||
|
CodexAvailabilityPatchInput,
|
||||||
|
type CodexReservationsResponse,
|
||||||
|
type CodexPurchaseIdsResponse,
|
||||||
|
type CodexPurchaseResponse,
|
||||||
|
type CodexPurchase,
|
||||||
|
type CodexStorageRequestCreateBody,
|
||||||
|
type CodexReservation,
|
||||||
|
type CodexPurchaseWithoutTypes,
|
||||||
|
} from "./types";
|
||||||
|
import {
|
||||||
CodexCreateAvailabilityInput,
|
CodexCreateAvailabilityInput,
|
||||||
CodexCreateStorageRequestInput,
|
CodexCreateStorageRequestInput,
|
||||||
type CodexPurchase,
|
|
||||||
type CodexReservation,
|
|
||||||
type CodexSlot,
|
|
||||||
type CodexStorageRequest,
|
|
||||||
CodexUpdateAvailabilityInput,
|
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export class CodexMarketplace {
|
export class CodexMarketplace {
|
||||||
@ -29,7 +40,7 @@ export class CodexMarketplace {
|
|||||||
async activeSlots(): Promise<SafeValue<CodexSlot[]>> {
|
async activeSlots(): Promise<SafeValue<CodexSlot[]>> {
|
||||||
const url = this.url + Api.config.prefix + "/sales/slots";
|
const url = this.url + Api.config.prefix + "/sales/slots";
|
||||||
|
|
||||||
return Fetch.safeJson<CodexSlot[]>(url, {
|
return Fetch.safeJson<CodexSlotResponse[]>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -37,21 +48,41 @@ export class CodexMarketplace {
|
|||||||
/**
|
/**
|
||||||
* Returns active slot with id {slotId} for the host
|
* Returns active slot with id {slotId} for the host
|
||||||
*/
|
*/
|
||||||
async activeSlot(slotId: string): Promise<SafeValue<CodexSlot>> {
|
async activeSlot(slotId: string): Promise<SafeValue<CodexSlotAgent>> {
|
||||||
const url = this.url + Api.config.prefix + "/sales/slots/" + slotId;
|
const url = this.url + Api.config.prefix + "/sales/slots/" + slotId;
|
||||||
|
|
||||||
return Fetch.safeJson<CodexSlot>(url, {
|
return Fetch.safeJson<CodexSlotAgentResponse>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private transformAvailability({
|
||||||
|
freeSize,
|
||||||
|
...a
|
||||||
|
}: CodexAvailabilityWithoutTypes) {
|
||||||
|
const availability: CodexAvailability = {
|
||||||
|
...a,
|
||||||
|
totalSize: parseInt(a.totalSize, 10),
|
||||||
|
duration: parseInt(a.duration, 10),
|
||||||
|
minPricePerBytePerSecond: parseInt(a.minPricePerBytePerSecond, 10),
|
||||||
|
totalCollateral: parseInt(a.totalCollateral, 10),
|
||||||
|
totalRemainingCollateral: parseInt(a.totalRemainingCollateral, 10),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (freeSize) {
|
||||||
|
availability.freeSize = parseInt(freeSize, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return availability;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns storage that is for sale
|
* Returns storage that is for sale
|
||||||
*/
|
*/
|
||||||
async availabilities(): Promise<SafeValue<CodexAvailability[]>> {
|
async availabilities(): Promise<SafeValue<CodexAvailability[]>> {
|
||||||
const url = this.url + Api.config.prefix + "/sales/availability";
|
const url = this.url + Api.config.prefix + "/sales/availability";
|
||||||
|
|
||||||
const res = await Fetch.safeJson<CodexAvailabilityDto[]>(url, {
|
const res = await Fetch.safeJson<CodexAvailabilityResponse>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -61,15 +92,7 @@ export class CodexMarketplace {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
error: false,
|
error: false,
|
||||||
data: res.data.map((a) => ({
|
data: res.data.map(this.transformAvailability),
|
||||||
id: a.id,
|
|
||||||
totalSize: parseInt(a.totalSize, 10),
|
|
||||||
freeSize: parseInt(a.freeSize, 10),
|
|
||||||
duration: parseInt(a.duration, 10),
|
|
||||||
minPricePerBytePerSecond: parseInt(a.minPricePerBytePerSecond, 10),
|
|
||||||
totalCollateral: parseInt(a.totalCollateral, 10),
|
|
||||||
totalRemainingCollateral: parseInt(a.totalRemainingCollateral, 10),
|
|
||||||
})),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +101,7 @@ export class CodexMarketplace {
|
|||||||
*/
|
*/
|
||||||
async createAvailability(
|
async createAvailability(
|
||||||
input: CodexCreateAvailabilityInput
|
input: CodexCreateAvailabilityInput
|
||||||
): Promise<SafeValue<CodexAvailabilityCreateResponse>> {
|
): Promise<SafeValue<CodexAvailability>> {
|
||||||
const result = v.safeParse(CodexCreateAvailabilityInput, input);
|
const result = v.safeParse(CodexCreateAvailabilityInput, input);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
@ -92,16 +115,31 @@ export class CodexMarketplace {
|
|||||||
|
|
||||||
const url = this.url + Api.config.prefix + "/sales/availability";
|
const url = this.url + Api.config.prefix + "/sales/availability";
|
||||||
|
|
||||||
const body = result.output;
|
const body: CodexAvailabilityCreateBody = {
|
||||||
|
totalSize: result.output.totalSize.toString(),
|
||||||
|
duration: result.output.duration.toString(),
|
||||||
|
minPricePerBytePerSecond:
|
||||||
|
result.output.minPricePerBytePerSecond.toString(),
|
||||||
|
totalCollateral: result.output.totalCollateral.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (result.output.enabled) {
|
||||||
|
body.enabled = result.output.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.output.until) {
|
||||||
|
body.until = result.output.until;
|
||||||
|
}
|
||||||
|
|
||||||
return Fetch.safeJson<CodexAvailabilityCreateResponse>(url, {
|
return Fetch.safeJson<CodexAvailabilityCreateResponse>(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify(body),
|
||||||
totalSize: body.totalSize.toString(),
|
}).then((result) => {
|
||||||
duration: body.duration.toString(),
|
if (result.error) {
|
||||||
minPricePerBytePerSecond: body.minPricePerBytePerSecond.toString(),
|
return result;
|
||||||
totalCollateral: body.totalCollateral.toString(),
|
}
|
||||||
}),
|
|
||||||
|
return { error: false, data: this.transformAvailability(result.data) };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,9 +148,9 @@ export class CodexMarketplace {
|
|||||||
* Existing Requests linked to this Availability will continue as is.
|
* Existing Requests linked to this Availability will continue as is.
|
||||||
*/
|
*/
|
||||||
async updateAvailability(
|
async updateAvailability(
|
||||||
input: CodexUpdateAvailabilityInput
|
input: CodexAvailabilityPatchInput
|
||||||
): Promise<SafeValue<"">> {
|
): Promise<SafeValue<"">> {
|
||||||
const result = v.safeParse(CodexUpdateAvailabilityInput, input);
|
const result = v.safeParse(CodexAvailabilityPatchInput, input);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
return {
|
return {
|
||||||
@ -126,16 +164,25 @@ export class CodexMarketplace {
|
|||||||
const url =
|
const url =
|
||||||
this.url + Api.config.prefix + "/sales/availability/" + result.output.id;
|
this.url + Api.config.prefix + "/sales/availability/" + result.output.id;
|
||||||
|
|
||||||
const body = result.output;
|
const body: CodexAvailabilityCreateBody = {
|
||||||
|
totalSize: result.output.totalSize.toString(),
|
||||||
|
duration: result.output.duration.toString(),
|
||||||
|
minPricePerBytePerSecond:
|
||||||
|
result.output.minPricePerBytePerSecond.toString(),
|
||||||
|
totalCollateral: result.output.totalCollateral.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (result.output.enabled) {
|
||||||
|
body.enabled = result.output.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.output.until) {
|
||||||
|
body.until = result.output.until;
|
||||||
|
}
|
||||||
|
|
||||||
const res = await Fetch.safe(url, {
|
const res = await Fetch.safe(url, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify(body),
|
||||||
totalSize: body.totalSize.toString(),
|
|
||||||
duration: body.duration.toString(),
|
|
||||||
minPricePerBytePerSecond: body.minPricePerBytePerSecond.toString(),
|
|
||||||
totalCollateral: body.totalCollateral.toString(),
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
@ -156,7 +203,7 @@ export class CodexMarketplace {
|
|||||||
Api.config.prefix +
|
Api.config.prefix +
|
||||||
`/sales/availability/${availabilityId}/reservations`;
|
`/sales/availability/${availabilityId}/reservations`;
|
||||||
|
|
||||||
return Fetch.safeJson<CodexReservation[]>(url, {
|
return Fetch.safeJson<CodexReservationsResponse>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -164,20 +211,48 @@ export class CodexMarketplace {
|
|||||||
/**
|
/**
|
||||||
* Returns list of purchase IDs
|
* Returns list of purchase IDs
|
||||||
*/
|
*/
|
||||||
async purchaseIds(): Promise<SafeValue<string[]>> {
|
async purchaseIds(): Promise<SafeValue<CodexPurchaseIdsResponse>> {
|
||||||
const url = this.url + Api.config.prefix + `/storage/purchases`;
|
const url = this.url + Api.config.prefix + `/storage/purchases`;
|
||||||
|
|
||||||
return Fetch.safeJson<string[]>(url, {
|
return Fetch.safeJson<CodexPurchaseIdsResponse>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async purchases(): Promise<SafeValue<CodexPurchase[]>> {
|
private transformPurchase(p: CodexPurchaseWithoutTypes): CodexPurchase {
|
||||||
const url = this.url + Api.config.prefix + `/storage/purchases`;
|
const purchase: CodexPurchase = {
|
||||||
|
requestId: p.requestId,
|
||||||
|
state: p.state,
|
||||||
|
};
|
||||||
|
|
||||||
const res = await Fetch.safeJson<string[]>(url, {
|
if (p.error) {
|
||||||
method: "GET",
|
purchase.error = p.error;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (!p.request) {
|
||||||
|
return purchase;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...purchase,
|
||||||
|
request: {
|
||||||
|
...p.request,
|
||||||
|
ask: {
|
||||||
|
...p.request.ask,
|
||||||
|
slotSize: parseInt(p.request.ask.slotSize, 10),
|
||||||
|
duration: parseInt(p.request.ask.duration, 10),
|
||||||
|
proofProbability: parseInt(p.request.ask.proofProbability, 10),
|
||||||
|
pricePerBytePerSecond: parseInt(
|
||||||
|
p.request.ask.pricePerBytePerSecond,
|
||||||
|
10
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async purchases(): Promise<SafeValue<CodexPurchase[]>> {
|
||||||
|
const res = await this.purchaseIds();
|
||||||
|
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
return res;
|
return res;
|
||||||
@ -199,7 +274,6 @@ export class CodexMarketplace {
|
|||||||
state: "error",
|
state: "error",
|
||||||
error: p.data.message,
|
error: p.data.message,
|
||||||
requestId: "",
|
requestId: "",
|
||||||
request: {} as CodexStorageRequest,
|
|
||||||
} satisfies CodexPurchase)
|
} satisfies CodexPurchase)
|
||||||
: p.data
|
: p.data
|
||||||
),
|
),
|
||||||
@ -213,8 +287,14 @@ export class CodexMarketplace {
|
|||||||
const url =
|
const url =
|
||||||
this.url + Api.config.prefix + `/storage/purchases/` + purchaseId;
|
this.url + Api.config.prefix + `/storage/purchases/` + purchaseId;
|
||||||
|
|
||||||
return Fetch.safeJson<CodexPurchase>(url, {
|
return Fetch.safeJson<CodexPurchaseResponse>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.error) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { error: false, data: this.transformPurchase(res.data) };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +327,7 @@ export class CodexMarketplace {
|
|||||||
} = result.output;
|
} = result.output;
|
||||||
const url = this.url + Api.config.prefix + "/storage/request/" + cid;
|
const url = this.url + Api.config.prefix + "/storage/request/" + cid;
|
||||||
|
|
||||||
const res = await Fetch.safe(url, {
|
return Fetch.safeText(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
duration: duration.toString(),
|
duration: duration.toString(),
|
||||||
@ -257,13 +337,7 @@ export class CodexMarketplace {
|
|||||||
collateralPerByte: collateralPerByte.toString(),
|
collateralPerByte: collateralPerByte.toString(),
|
||||||
expiry: expiry.toString(),
|
expiry: expiry.toString(),
|
||||||
tolerance,
|
tolerance,
|
||||||
}),
|
} satisfies CodexStorageRequestCreateBody),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.error) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { error: false, data: await res.data.text() };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,232 +1,122 @@
|
|||||||
|
import type { components, paths } from "../openapi";
|
||||||
import * as v from "valibot";
|
import * as v from "valibot";
|
||||||
|
|
||||||
export type CodexStorageRequest = {
|
export type CodexSlotResponse =
|
||||||
id: string;
|
paths["/sales/slots"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
|
|
||||||
/**
|
export type CodexSlot = CodexSlotResponse;
|
||||||
* Address of Ethereum address
|
|
||||||
*/
|
|
||||||
client: string;
|
|
||||||
|
|
||||||
ask: {
|
export type CodexSlotAgentResponse =
|
||||||
/**
|
paths["/sales/slots/{slotId}"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
* Number of slots that the tequest want to have the content spread over.
|
|
||||||
*/
|
|
||||||
slots: number;
|
|
||||||
|
|
||||||
/**
|
export type CodexSlotAgent = CodexSlotAgentResponse;
|
||||||
* Amount of storage per slot (in bytes) as decimal string.
|
|
||||||
*/
|
|
||||||
slotSize: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexAvailabilityResponse =
|
||||||
* The duration of the storage request in seconds.
|
paths["/sales/availability"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
*/
|
|
||||||
duration: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexAvailabilityWithoutTypes =
|
||||||
* How often storage proofs are required as decimal string (in periods).
|
components["schemas"]["SalesAvailabilityREAD"];
|
||||||
*/
|
|
||||||
proofProbability: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexAvailability = Omit<
|
||||||
* The amount of tokens paid per byte per second per slot to hosts the client is willing to pay
|
CodexAvailabilityWithoutTypes,
|
||||||
*/
|
| "freeSize"
|
||||||
pricePerBytePerSecond: string;
|
| "totalSize"
|
||||||
|
| "minPricePerBytePerSecond"
|
||||||
/**
|
| "duration"
|
||||||
* Max slots that can be lost without data considered to be lost.
|
| "totalCollateral"
|
||||||
*/
|
| "totalRemainingCollateral"
|
||||||
maxSlotLoss: number;
|
> & {
|
||||||
};
|
freeSize?: number;
|
||||||
|
|
||||||
content: {
|
|
||||||
/**
|
|
||||||
* Unique Content ID
|
|
||||||
*/
|
|
||||||
cid: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Erasure code parameters
|
|
||||||
*/
|
|
||||||
// erasure: {
|
|
||||||
/**
|
|
||||||
* Total number of chunks generated by the erasure code process.
|
|
||||||
*/
|
|
||||||
// totalChunks: number;
|
|
||||||
// };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameters for Proof of Retrievability
|
|
||||||
*/
|
|
||||||
// por: {
|
|
||||||
// u: string;
|
|
||||||
// publicKey: string;
|
|
||||||
// name: string;
|
|
||||||
// };
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Number as decimal string that represents expiry threshold in seconds from when the Request is submitted.
|
|
||||||
* When the threshold is reached and the Request does not find requested amount of nodes to host the data, the Request is voided.
|
|
||||||
* The number of seconds can not be higher then the Request's duration itself.
|
|
||||||
*/
|
|
||||||
expiry: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Random data
|
|
||||||
*/
|
|
||||||
nonce: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A storage slot is a portion of a storage contract that needs to be fulfilled
|
|
||||||
* by a host. To initiate a contract, all the slots must be filled.
|
|
||||||
*/
|
|
||||||
export type CodexSlot = {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
request: CodexStorageRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The slot index as hexadecimal string
|
|
||||||
*/
|
|
||||||
slotIndex: "string";
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Storage availability for sell.
|
|
||||||
*/
|
|
||||||
export type CodexAvailability = {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size of available storage in bytes
|
|
||||||
*/
|
|
||||||
totalSize: number;
|
totalSize: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Unused size of availability's storage in bytes as decimal string
|
|
||||||
*/
|
|
||||||
freeSize: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum time the storage should be sold for (in seconds)
|
|
||||||
*/
|
|
||||||
duration: number;
|
duration: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimal price per byte per second paid (in amount of tokens) for the
|
|
||||||
* hosted request's slot for the request's duration as decimal string
|
|
||||||
*/
|
|
||||||
minPricePerBytePerSecond: number;
|
minPricePerBytePerSecond: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Total collateral (in amount of tokens) that can be used for matching requests
|
|
||||||
*/
|
|
||||||
totalCollateral: number;
|
totalCollateral: number;
|
||||||
|
|
||||||
totalRemainingCollateral: number;
|
totalRemainingCollateral: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export type CodexAvailabilityCreateResponse =
|
||||||
* Storage availability received from the api.
|
paths["/sales/availability"]["post"]["responses"][201]["content"]["application/json"];
|
||||||
*/
|
|
||||||
export type CodexAvailabilityDto = {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexAvailabilityCreateBody = Exclude<
|
||||||
* Size of available storage in bytes
|
paths["/sales/availability"]["post"]["requestBody"],
|
||||||
*/
|
undefined
|
||||||
totalSize: string;
|
>["content"]["application/json"];
|
||||||
|
|
||||||
/**
|
|
||||||
* Unused size of availability's storage in bytes as decimal string
|
|
||||||
*/
|
|
||||||
freeSize: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum time the storage should be sold for (in seconds)
|
|
||||||
*/
|
|
||||||
duration: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimal price per byte per second paid (in amount of tokens) for the
|
|
||||||
* hosted request's slot for the request's duration as decimal string
|
|
||||||
*/
|
|
||||||
minPricePerBytePerSecond: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Total collateral (in amount of tokens) that can be used for matching requests
|
|
||||||
*/
|
|
||||||
totalCollateral: string;
|
|
||||||
|
|
||||||
totalRemainingCollateral: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CodexAvailabilityCreateResponse = CodexAvailability & {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unused size of availability's storage in bytes as decimal string
|
|
||||||
*/
|
|
||||||
freeSize: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CodexCreateAvailabilityInput = v.strictObject({
|
export const CodexCreateAvailabilityInput = v.strictObject({
|
||||||
totalSize: v.pipe(v.number(), v.minValue(1)),
|
totalSize: v.pipe(v.number(), v.minValue(1)),
|
||||||
duration: v.pipe(v.number(), v.minValue(1)),
|
duration: v.pipe(v.number(), v.minValue(1)),
|
||||||
minPricePerBytePerSecond: v.number(),
|
minPricePerBytePerSecond: v.number(),
|
||||||
totalCollateral: v.number(),
|
totalCollateral: v.number(),
|
||||||
|
enabled: v.optional(v.boolean()),
|
||||||
|
until: v.optional(v.number()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type CodexAvailabilityPatchResponse =
|
||||||
|
paths["/sales/availability/{id}"]["patch"]["responses"][204]["content"];
|
||||||
|
|
||||||
|
export type CodexAvailabilityPatchBody = Exclude<
|
||||||
|
paths["/sales/availability"]["post"]["requestBody"],
|
||||||
|
undefined
|
||||||
|
>["content"]["application/json"];
|
||||||
|
|
||||||
export type CodexCreateAvailabilityInput = v.InferOutput<
|
export type CodexCreateAvailabilityInput = v.InferOutput<
|
||||||
typeof CodexCreateAvailabilityInput
|
typeof CodexCreateAvailabilityInput
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const CodexUpdateAvailabilityInput = v.strictObject({
|
export const CodexAvailabilityPatchInput = v.strictObject({
|
||||||
id: v.string(),
|
id: v.string(),
|
||||||
totalSize: v.pipe(v.number(), v.minValue(1)),
|
totalSize: v.pipe(v.number(), v.minValue(1)),
|
||||||
duration: v.pipe(v.number(), v.minValue(1)),
|
duration: v.pipe(v.number(), v.minValue(1)),
|
||||||
minPricePerBytePerSecond: v.number(),
|
minPricePerBytePerSecond: v.number(),
|
||||||
totalCollateral: v.number(),
|
totalCollateral: v.number(),
|
||||||
|
enabled: v.optional(v.boolean()),
|
||||||
|
until: v.optional(v.number()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CodexUpdateAvailabilityInput = v.InferOutput<
|
export type CodexAvailabilityPatchInput = v.InferOutput<
|
||||||
typeof CodexUpdateAvailabilityInput
|
typeof CodexAvailabilityPatchInput
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type CodexReservation = {
|
export type CodexReservationsResponse =
|
||||||
id: string;
|
paths["/sales/availability/{id}/reservations"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
availabilityId: string;
|
|
||||||
requestId: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexReservation = components["schemas"]["Reservation"];
|
||||||
* Size in bytes
|
|
||||||
*/
|
|
||||||
size: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexPurchaseIdsResponse =
|
||||||
* Slot Index as hexadecimal string
|
paths["/storage/purchases"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
*/
|
|
||||||
slotIndex: string;
|
export type CodexPurchaseResponse =
|
||||||
|
paths["/storage/purchases/{id}"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
|
|
||||||
|
export type CodexStorageAsk = Omit<
|
||||||
|
components["schemas"]["StorageAsk"],
|
||||||
|
"slotSize" | "duration" | "proofProbability" | "pricePerBytePerSecond"
|
||||||
|
> & {
|
||||||
|
slotSize: number;
|
||||||
|
duration: number;
|
||||||
|
proofProbability: number;
|
||||||
|
pricePerBytePerSecond: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CodexPurchase = {
|
export type CodexPurchaseWithoutTypes = components["schemas"]["Purchase"];
|
||||||
/**
|
|
||||||
* Description of the request's state
|
|
||||||
*/
|
|
||||||
state: string;
|
|
||||||
|
|
||||||
/**
|
export type CodexPurchase = Omit<
|
||||||
* If request failed, then here is presented the error message
|
components["schemas"]["Purchase"],
|
||||||
*/
|
"request"
|
||||||
error: string;
|
> & {
|
||||||
|
request?: Omit<components["schemas"]["StorageRequest"], "ask"> & {
|
||||||
request: CodexStorageRequest;
|
ask: CodexStorageAsk;
|
||||||
|
};
|
||||||
requestId: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CodexStorageRequestResponse =
|
||||||
|
paths["/storage/request/{cid}"]["post"]["responses"][200]["content"]["text/plain"];
|
||||||
|
|
||||||
|
export type CodexStorageRequestCreateBody = Exclude<
|
||||||
|
paths["/storage/request/{cid}"]["post"]["requestBody"],
|
||||||
|
undefined
|
||||||
|
>["content"]["application/json"];
|
||||||
|
|
||||||
export const CodexCreateStorageRequestInput = v.strictObject({
|
export const CodexCreateStorageRequestInput = v.strictObject({
|
||||||
cid: v.string(),
|
cid: v.string(),
|
||||||
duration: v.pipe(v.number(), v.minValue(1)),
|
duration: v.pipe(v.number(), v.minValue(1)),
|
||||||
|
|||||||
@ -1,7 +1,14 @@
|
|||||||
import { Api } from "../api/config";
|
import { Api } from "../api/config";
|
||||||
import { Fetch } from "../fetch-safe/fetch-safe";
|
import { Fetch } from "../fetch-safe/fetch-safe";
|
||||||
import type { SafeValue } from "../values/values";
|
import type { SafeValue } from "../values/values";
|
||||||
import type { CodexSpr } from "./types";
|
import type {
|
||||||
|
CodexPeerId,
|
||||||
|
CodexPeerIdContentType,
|
||||||
|
CodexPeerIdJsonResponse,
|
||||||
|
CodexSpr,
|
||||||
|
CodexSprContentType,
|
||||||
|
CodexSprJsonResponse,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
export class CodexNode {
|
export class CodexNode {
|
||||||
readonly url: string;
|
readonly url: string;
|
||||||
@ -12,9 +19,8 @@ export class CodexNode {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a peer
|
* Connect to a peer
|
||||||
* TODO check result
|
|
||||||
*/
|
*/
|
||||||
connect(peerId: string, addrs: string[] = []) {
|
connect(peerId: string, addrs: string[] = []): Promise<SafeValue<string>> {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
for (const addr of addrs) {
|
for (const addr of addrs) {
|
||||||
@ -24,7 +30,7 @@ export class CodexNode {
|
|||||||
const url =
|
const url =
|
||||||
this.url + Api.config.prefix + `/connect/${peerId}?` + params.toString();
|
this.url + Api.config.prefix + `/connect/${peerId}?` + params.toString();
|
||||||
|
|
||||||
return Fetch.safe(url, {
|
return Fetch.safeText(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -32,23 +38,50 @@ export class CodexNode {
|
|||||||
/**
|
/**
|
||||||
* Get Node's SPR
|
* Get Node's SPR
|
||||||
*/
|
*/
|
||||||
async spr(): Promise<SafeValue<CodexSpr>> {
|
async spr(
|
||||||
|
type: CodexSprContentType = "json"
|
||||||
|
): Promise<SafeValue<CodexSpr<CodexSprContentType>>> {
|
||||||
const url = this.url + Api.config.prefix + "/spr";
|
const url = this.url + Api.config.prefix + "/spr";
|
||||||
|
|
||||||
return Fetch.safeJson(url, {
|
if (type === "json") {
|
||||||
|
return Fetch.safeJson<CodexSprJsonResponse>(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Fetch.safeText(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "text/plain",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Node's PeerID
|
* Get Node's PeerID
|
||||||
* TODO check result
|
|
||||||
*/
|
*/
|
||||||
peerId() {
|
peerId(
|
||||||
|
type: CodexPeerIdContentType = "json"
|
||||||
|
): Promise<SafeValue<CodexPeerId<CodexPeerIdContentType>>> {
|
||||||
const url = this.url + Api.config.prefix + "/node/peerid";
|
const url = this.url + Api.config.prefix + "/node/peerid";
|
||||||
|
|
||||||
return Fetch.safe(url, {
|
if (type === "json") {
|
||||||
|
return Fetch.safeJson<CodexPeerIdJsonResponse>(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Fetch.safeText(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "text/plain",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,29 @@
|
|||||||
export type CodexSpr = {
|
import type { paths } from "../openapi";
|
||||||
spr: string;
|
|
||||||
};
|
export type CodexSprTextResponse =
|
||||||
|
paths["/spr"]["get"]["responses"][200]["content"]["text/plain"];
|
||||||
|
|
||||||
|
export type CodexSprJsonResponse =
|
||||||
|
paths["/spr"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
|
|
||||||
|
export type CodexSprContentType = "json" | "text";
|
||||||
|
|
||||||
|
export type CodexSpr<T extends CodexSprContentType> = T extends "json"
|
||||||
|
? CodexSprJsonResponse
|
||||||
|
: T extends "text"
|
||||||
|
? CodexSprTextResponse
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type CodexPeerIdTextResponse =
|
||||||
|
paths["/peerid"]["get"]["responses"][200]["content"]["text/plain"];
|
||||||
|
|
||||||
|
export type CodexPeerIdJsonResponse =
|
||||||
|
paths["/peerid"]["get"]["responses"][200]["content"]["application/json"];
|
||||||
|
|
||||||
|
export type CodexPeerIdContentType = "json" | "text";
|
||||||
|
|
||||||
|
export type CodexPeerId<T extends CodexPeerIdContentType> = T extends "json"
|
||||||
|
? CodexPeerIdJsonResponse
|
||||||
|
: T extends "text"
|
||||||
|
? CodexPeerIdTextResponse
|
||||||
|
: never;
|
||||||
|
|||||||
1418
src/openapi.ts
Normal file
1418
src/openapi.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
|||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "Bundler",
|
"moduleResolution": "Bundler",
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
"sourceMap": true
|
"sourceMap": true,
|
||||||
|
"noUncheckedIndexedAccess": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user