mirror of
https://github.com/logos-storage/logos-storage-js.git
synced 2026-01-02 13:33:07 +00:00
chore: generate types from open api (#14)
* Generate types from the open api file * Update dependencies * Update dependencies * Update the openapi schema * Fix merge * Fix doc reference
This commit is contained in:
parent
921bb617ef
commit
3bf517d1bb
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
dist
|
||||
*.tgz
|
||||
index.bundle.js
|
||||
78
README.md
78
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.
|
||||
|
||||
## 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
|
||||
|
||||
### Sync api
|
||||
@ -126,7 +134,7 @@ const marketplace = codex.marketplace;
|
||||
|
||||
Returns active slots.
|
||||
|
||||
- returns Promise<[CodexSlot](./src/marketplace/types.ts#L85)[]>
|
||||
- returns Promise<[CodexSlot](./src/marketplace/types.ts#L7)[]>
|
||||
|
||||
Example:
|
||||
|
||||
@ -139,7 +147,7 @@ const slots = await marketplace.activeSlots();
|
||||
Returns active slot with id {slotId} for the host.
|
||||
|
||||
- slotId (string, required)
|
||||
- returns Promise<[CodexSlot](./src/marketplace/types.ts#L85)[]>
|
||||
- returns Promise<[CodexSlotAgent](./src/marketplace/types.ts#L12)[]>
|
||||
|
||||
Example:
|
||||
|
||||
@ -152,7 +160,7 @@ const slot = await marketplace.activeSlot(slotId);
|
||||
|
||||
Returns storage that is for sale.
|
||||
|
||||
- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L99)>
|
||||
- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L20)>
|
||||
|
||||
Example:
|
||||
|
||||
@ -164,8 +172,8 @@ const availabilities = await marketplace.availabilities();
|
||||
|
||||
Offers storage for sale.
|
||||
|
||||
- input ([CodexCreateAvailabilityInput](./src/marketplace/types.ts#L175), required)
|
||||
- returns Promise<[CodexAvailabilityCreateResponse](./src/marketplace/types.ts#L186)[]>
|
||||
- input ([CodexCreateAvailabilityInput](./src/marketplace/types.ts#L45), required)
|
||||
- returns Promise<[CodexAvailability](./src/marketplace/types.ts#L20)[]>
|
||||
|
||||
Example:
|
||||
|
||||
@ -182,7 +190,7 @@ const response = await marketplace.createAvailability({
|
||||
|
||||
Updates availability.
|
||||
|
||||
- input ([CodexUpdateAvailabilityInput](./src/marketplace/types.ts#L186), required)
|
||||
- input ([CodexAvailabilityPatchInput](./src/marketplace/types.ts#L66), required)
|
||||
- returns Promise<"">
|
||||
|
||||
Example:
|
||||
@ -202,7 +210,7 @@ const response = await marketplace.updateAvailability({
|
||||
Return list of reservations for ongoing Storage Requests that the node hosts.
|
||||
|
||||
- availabilityId (string, required)
|
||||
- returns Promise<[CodexReservation](./src/marketplace/types.ts#L198)[]>
|
||||
- returns Promise<[CodexReservation](./src/marketplace/types.ts#L83)[]>
|
||||
|
||||
Example:
|
||||
|
||||
@ -214,7 +222,7 @@ const reservations = await marketplace.reservations("Ox...");
|
||||
|
||||
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>
|
||||
|
||||
Example:
|
||||
@ -248,7 +256,7 @@ const ids = await marketplace.purchaseIds();
|
||||
Returns purchase details
|
||||
|
||||
- purchaseId (string, required)
|
||||
- returns Promise<[CodexPurchase](./src/marketplace/types.ts#L214)[]>
|
||||
- returns Promise<[CodexPurchase](./src/marketplace/types.ts#L103)[]>
|
||||
|
||||
Example:
|
||||
|
||||
@ -274,7 +282,7 @@ const data = codex.data;
|
||||
|
||||
Returns the manifest stored locally in node.
|
||||
|
||||
- returns Promise<[CodexDataResponse](./src/data/types.ts#L54)[]>
|
||||
- returns Promise<[CodexDataItem](./src/data/types.ts#L8)[]>
|
||||
|
||||
Example:
|
||||
|
||||
@ -286,7 +294,7 @@ const cids = await data.cids();
|
||||
|
||||
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#L15)[]>
|
||||
|
||||
Example:
|
||||
|
||||
@ -301,7 +309,7 @@ Upload a file in a streaming manner
|
||||
#### Browser
|
||||
|
||||
- stategy [BrowserUploadStategy](./src/data/browser-upload.ts#L5)
|
||||
- returns [UploadResponse](./src/data/types.ts#L80)
|
||||
- returns [UploadResponse](./src/data/types.ts#L17)
|
||||
|
||||
Example:
|
||||
|
||||
@ -330,8 +338,8 @@ console.info("CID is", res.data);
|
||||
|
||||
#### Node
|
||||
|
||||
- stategy [NodeUploadStategy](./src/data/node-download.ts#L8)
|
||||
- returns [UploadResponse](./src/data/types.ts#L80)
|
||||
- stategy [NodeUploadStategy](./src/data/node-upload.ts#L9)
|
||||
- returns [UploadResponse](./src/data/types.ts#L17)
|
||||
|
||||
Example:
|
||||
|
||||
@ -354,7 +362,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.
|
||||
|
||||
- cid (string, required)
|
||||
- returns [CodexManifest](./src/data/types.ts#L3)
|
||||
- returns [CodexManifest](./src/data/types.ts#L30)
|
||||
|
||||
Example:
|
||||
|
||||
@ -410,7 +418,7 @@ const data = codex.debug;
|
||||
|
||||
Set log level at run time.
|
||||
|
||||
- level ([CodexLogLevel](./src/debug/types.ts#L3), required)
|
||||
- level ([CodexLogLevel](./src/debug/types.ts#L7), required)
|
||||
- returns Promise<"">
|
||||
|
||||
Example:
|
||||
@ -423,7 +431,7 @@ await debug.setLogLevel("DEBUG");
|
||||
|
||||
Gets node information
|
||||
|
||||
- returns Promise<[CodexDebugInfo](./src/debug/types.ts#L15)>
|
||||
- returns Promise<[CodexDebugInfo](./src/debug/types.ts#L23)>
|
||||
|
||||
Example:
|
||||
|
||||
@ -448,10 +456,44 @@ const node = codex.node;
|
||||
|
||||
Get Node's SPR
|
||||
|
||||
- returns Promise<[CodexSpr](./src/node/types.ts#L1)>
|
||||
- returns Promise<[CodexSpr](./src/node/types.ts#L11)>
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
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);
|
||||
```
|
||||
|
||||
15
examples/upload-node/package-lock.json
generated
15
examples/upload-node/package-lock.json
generated
@ -10,7 +10,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@codex-storage/sdk-js": "../..",
|
||||
"undici": "^7.6.0"
|
||||
"undici": "^7.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.5.3"
|
||||
@ -24,11 +24,14 @@
|
||||
"version": "0.1.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"valibot": "^0.32.0"
|
||||
"undici": "^7.7.0",
|
||||
"valibot": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"@types/node": "^22.13.13",
|
||||
"@types/node": "^22.13.17",
|
||||
"oas-normalize": "^13.1.2",
|
||||
"openapi-typescript": "^7.6.1",
|
||||
"prettier": "^3.5.3",
|
||||
"tsup": "^8.3.6",
|
||||
"typescript": "^5.8.2",
|
||||
@ -65,9 +68,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.6.0.tgz",
|
||||
"integrity": "sha512-gaFsbThjrDGvAaD670r81RZro/s6H2PVZF640Qn0p5kZK+/rim7/mmyfp2W7VB5vOMaFM8vuFBJUaMlaZTYHlA==",
|
||||
"version": "7.7.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.7.0.tgz",
|
||||
"integrity": "sha512-tZ6+5NBq4KH35rr46XJ2JPFKxfcBlYNaqLF/wyWIO9RMHqqU/gx/CLB1Y2qMcgB8lWw/bKHa7qzspqCN7mUHvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
|
||||
@ -2,15 +2,13 @@
|
||||
"name": "@codex-storage/sdk-js-update-node-example",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "node esbuild.js"
|
||||
},
|
||||
"scripts": {},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@codex-storage/sdk-js": "../..",
|
||||
"undici": "^7.6.0"
|
||||
"undici": "^7.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.5.3"
|
||||
|
||||
1012
openapi.yaml
Normal file
1012
openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
1142
package-lock.json
generated
1142
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -77,16 +77,18 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"@types/node": "^22.13.14",
|
||||
"@types/node": "^22.13.17",
|
||||
"oas-normalize": "^13.1.2",
|
||||
"openapi-typescript": "^7.6.1",
|
||||
"prettier": "^3.5.3",
|
||||
"tsup": "^8.3.6",
|
||||
"typescript": "^5.8.2",
|
||||
"vitest": "^3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"valibot": "^0.32.0"
|
||||
"valibot": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"undici": "^7.0.0"
|
||||
"undici": "^7.7.0"
|
||||
}
|
||||
}
|
||||
@ -7,11 +7,14 @@ import {
|
||||
import type { SafeValue } from "../values/values";
|
||||
import type {
|
||||
CodexDataResponse,
|
||||
CodexManifest,
|
||||
CodexNodeSpace,
|
||||
UploadStategy,
|
||||
NetworkDownloadResponse,
|
||||
UploadResponse,
|
||||
CodexSpaceResponse,
|
||||
CodexNodeSpace,
|
||||
CodexDataNetworkResponse,
|
||||
CodexNetworkDownload,
|
||||
CodexManifest,
|
||||
CodexDataItems,
|
||||
} from "./types";
|
||||
|
||||
type CodexDataOptions = {
|
||||
@ -34,7 +37,7 @@ export class CodexData {
|
||||
* Lists manifest CIDs stored locally in node.
|
||||
* 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";
|
||||
|
||||
return Fetch.safeJson<CodexDataResponse>(url, {
|
||||
@ -52,10 +55,10 @@ export class CodexData {
|
||||
/**
|
||||
* Gets a summary of the storage space allocation of the node.
|
||||
*/
|
||||
space() {
|
||||
space(): Promise<SafeValue<CodexNodeSpace>> {
|
||||
const url = this.url + Api.config.prefix + "/space";
|
||||
|
||||
return Fetch.safeJson<CodexNodeSpace>(url, {
|
||||
return Fetch.safeJson<CodexSpaceResponse>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
@ -95,12 +98,10 @@ export class CodexData {
|
||||
* 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.
|
||||
*/
|
||||
async networkDownload(
|
||||
cid: string
|
||||
): Promise<SafeValue<NetworkDownloadResponse>> {
|
||||
async networkDownload(cid: string): Promise<SafeValue<CodexNetworkDownload>> {
|
||||
const url = this.url + Api.config.prefix + `/data/${cid}/network`;
|
||||
|
||||
return Fetch.safeJson(url, {
|
||||
return Fetch.safeJson<CodexDataNetworkResponse>(url, {
|
||||
method: "POST",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
@ -123,7 +124,7 @@ export class CodexData {
|
||||
* Download only the dataset manifest from the network to the local node
|
||||
* 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`;
|
||||
|
||||
return Fetch.safeJson<CodexManifest>(url, {
|
||||
|
||||
@ -1,87 +1,33 @@
|
||||
import type { components, paths } from "../openapi";
|
||||
import type { FetchAuth } from "../fetch-safe/fetch-safe";
|
||||
import type { SafeValue } from "../values/values";
|
||||
|
||||
export type CodexManifest = {
|
||||
/**
|
||||
* "Root hash of the content"
|
||||
*/
|
||||
// rootHash: string;
|
||||
export type CodexDataResponse =
|
||||
paths["/data"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
/**
|
||||
* Length of original content in bytes
|
||||
*/
|
||||
// originalBytes: number;
|
||||
export type CodexDataItem = components["schemas"]["DataItem"];
|
||||
|
||||
/**
|
||||
* Total size of all blocks
|
||||
*/
|
||||
datasetSize: number;
|
||||
export type CodexDataItems = CodexDataResponse;
|
||||
|
||||
/**
|
||||
* "Size of blocks"
|
||||
*/
|
||||
blockSize: number;
|
||||
export type CodexSpaceResponse =
|
||||
paths["/space"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
/**
|
||||
* 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 CodexNodeSpace = CodexSpaceResponse;
|
||||
|
||||
export type UploadResponse = {
|
||||
result: Promise<SafeValue<string>>;
|
||||
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 type UploadStategyOptions = {
|
||||
auth?: FetchAuth;
|
||||
|
||||
@ -6,7 +6,12 @@ import {
|
||||
type FetchAuth,
|
||||
} from "../fetch-safe/fetch-safe";
|
||||
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";
|
||||
|
||||
type CodexDebugOptions = {
|
||||
@ -28,8 +33,8 @@ export class CodexDebug {
|
||||
/**
|
||||
* Set log level at run time
|
||||
*/
|
||||
async setLogLevel(level: CodexLogLevel): Promise<SafeValue<"">> {
|
||||
const result = v.safeParse(CodexLogLevel, level);
|
||||
async setLogLevel(level: CodexLogLevel): Promise<SafeValue<string>> {
|
||||
const result = v.safeParse(CodexLogLevelInput, level);
|
||||
|
||||
if (!result.success) {
|
||||
return Promise.resolve({
|
||||
@ -46,26 +51,20 @@ export class CodexDebug {
|
||||
"/debug/chronicles/loglevel?level=" +
|
||||
level;
|
||||
|
||||
const res = await Fetch.safe(url, {
|
||||
return Fetch.safeText(url, {
|
||||
method: "POST",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
body: "",
|
||||
});
|
||||
|
||||
if (res.error) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return { error: false, data: "" };
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets node information
|
||||
*/
|
||||
info() {
|
||||
info(): Promise<SafeValue<CodexDebugInfo>> {
|
||||
const url = this.url + Api.config.prefix + `/debug/info`;
|
||||
|
||||
return Fetch.safeJson<CodexDebugInfo>(url, {
|
||||
return Fetch.safeJson<CodexInfoResponse>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
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",
|
||||
"DEBUG",
|
||||
"INFO",
|
||||
@ -10,49 +17,7 @@ export const CodexLogLevel = v.picklist([
|
||||
"FATAL",
|
||||
]);
|
||||
|
||||
export type CodexLogLevel = v.InferOutput<typeof CodexLogLevel>;
|
||||
export type CodexInfoResponse =
|
||||
paths["/debug/info"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
export type CodexDebugInfo = {
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
};
|
||||
export type CodexDebugInfo = CodexInfoResponse;
|
||||
|
||||
@ -60,4 +60,14 @@ export const Fetch = {
|
||||
|
||||
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() {
|
||||
return {
|
||||
id: randomEthereumAddress(),
|
||||
totalSize: randomInt(0, 9).toString(),
|
||||
duration: randomInt(0, 9).toString(),
|
||||
minPrice: randomInt(0, 9).toString(),
|
||||
maxCollateral: randomInt(0, 9).toString(),
|
||||
totalSize: randomInt(0, 9),
|
||||
duration: randomInt(0, 9),
|
||||
minPrice: randomInt(0, 9),
|
||||
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 () => {
|
||||
const data = { ...createAvailability(), freeSize: "1000" };
|
||||
const data = { ...createAvailability(), freeSize: 1000 };
|
||||
|
||||
const spy = vi.spyOn(Fetch, "safeJson");
|
||||
spy.mockImplementationOnce(() => Promise.resolve({ error: false, data }));
|
||||
@ -228,16 +230,16 @@ describe("marketplace", () => {
|
||||
});
|
||||
|
||||
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");
|
||||
spy.mockImplementationOnce(() => Promise.resolve({ error: false, data }));
|
||||
|
||||
const response = await marketplace.createAvailability({
|
||||
totalCollateral: 1,
|
||||
totalSize: 3000,
|
||||
minPricePerBytePerSecond: 100,
|
||||
duration: 100,
|
||||
totalCollateral: data.totalCollateral,
|
||||
totalSize: data.totalSize,
|
||||
minPricePerBytePerSecond: data.minPricePerBytePerSecond,
|
||||
duration: data.duration,
|
||||
});
|
||||
|
||||
assert.ok(!response.error);
|
||||
|
||||
@ -8,16 +8,27 @@ import {
|
||||
} from "../fetch-safe/fetch-safe";
|
||||
import type { SafeValue } from "../values/values";
|
||||
import {
|
||||
type CodexAvailabilityResponse,
|
||||
type CodexAvailability,
|
||||
type CodexSlot,
|
||||
type CodexSlotAgent,
|
||||
type CodexSlotResponse,
|
||||
type CodexSlotAgentResponse,
|
||||
type CodexAvailabilityWithoutTypes,
|
||||
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,
|
||||
CodexCreateStorageRequestInput,
|
||||
type CodexPurchase,
|
||||
type CodexReservation,
|
||||
type CodexSlot,
|
||||
type CodexStorageRequest,
|
||||
CodexUpdateAvailabilityInput,
|
||||
} from "./types";
|
||||
|
||||
type CodexMarketplaceOptions = {
|
||||
@ -42,7 +53,7 @@ export class CodexMarketplace {
|
||||
async activeSlots(): Promise<SafeValue<CodexSlot[]>> {
|
||||
const url = this.url + Api.config.prefix + "/sales/slots";
|
||||
|
||||
return Fetch.safeJson<CodexSlot[]>(url, {
|
||||
return Fetch.safeJson<CodexSlotResponse[]>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
@ -51,22 +62,40 @@ export class CodexMarketplace {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
return Fetch.safeJson<CodexSlot>(url, {
|
||||
return Fetch.safeJson<CodexSlotAgentResponse>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
|
||||
private transformAvailability({
|
||||
freeSize,
|
||||
...a
|
||||
}: CodexAvailabilityWithoutTypes) {
|
||||
const availability: CodexAvailability = {
|
||||
...a,
|
||||
minPricePerBytePerSecond: parseInt(a.minPricePerBytePerSecond, 10),
|
||||
totalCollateral: parseInt(a.totalCollateral, 10),
|
||||
totalRemainingCollateral: parseInt(a.totalRemainingCollateral, 10),
|
||||
};
|
||||
|
||||
if (freeSize) {
|
||||
availability.freeSize = freeSize;
|
||||
}
|
||||
|
||||
return availability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns storage that is for sale
|
||||
*/
|
||||
async availabilities(): Promise<SafeValue<CodexAvailability[]>> {
|
||||
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",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
@ -77,15 +106,7 @@ export class CodexMarketplace {
|
||||
|
||||
return {
|
||||
error: false,
|
||||
data: res.data.map((a) => ({
|
||||
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),
|
||||
})),
|
||||
data: res.data.map(this.transformAvailability),
|
||||
};
|
||||
}
|
||||
|
||||
@ -94,7 +115,7 @@ export class CodexMarketplace {
|
||||
*/
|
||||
async createAvailability(
|
||||
input: CodexCreateAvailabilityInput
|
||||
): Promise<SafeValue<CodexAvailabilityCreateResponse>> {
|
||||
): Promise<SafeValue<CodexAvailability>> {
|
||||
const result = v.safeParse(CodexCreateAvailabilityInput, input);
|
||||
|
||||
if (!result.success) {
|
||||
@ -108,17 +129,32 @@ export class CodexMarketplace {
|
||||
|
||||
const url = this.url + Api.config.prefix + "/sales/availability";
|
||||
|
||||
const body = result.output;
|
||||
const body: CodexAvailabilityCreateBody = {
|
||||
totalSize: result.output.totalSize,
|
||||
duration: result.output.duration,
|
||||
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, {
|
||||
method: "POST",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
body: JSON.stringify({
|
||||
totalSize: body.totalSize.toString(),
|
||||
duration: body.duration.toString(),
|
||||
minPricePerBytePerSecond: body.minPricePerBytePerSecond.toString(),
|
||||
totalCollateral: body.totalCollateral.toString(),
|
||||
}),
|
||||
body: JSON.stringify(body),
|
||||
}).then((result) => {
|
||||
if (result.error) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return { error: false, data: this.transformAvailability(result.data) };
|
||||
});
|
||||
}
|
||||
|
||||
@ -127,9 +163,9 @@ export class CodexMarketplace {
|
||||
* Existing Requests linked to this Availability will continue as is.
|
||||
*/
|
||||
async updateAvailability(
|
||||
input: CodexUpdateAvailabilityInput
|
||||
input: CodexAvailabilityPatchInput
|
||||
): Promise<SafeValue<"">> {
|
||||
const result = v.safeParse(CodexUpdateAvailabilityInput, input);
|
||||
const result = v.safeParse(CodexAvailabilityPatchInput, input);
|
||||
|
||||
if (!result.success) {
|
||||
return {
|
||||
@ -143,17 +179,26 @@ export class CodexMarketplace {
|
||||
const url =
|
||||
this.url + Api.config.prefix + "/sales/availability/" + result.output.id;
|
||||
|
||||
const body = result.output;
|
||||
const body: CodexAvailabilityCreateBody = {
|
||||
totalSize: result.output.totalSize,
|
||||
duration: result.output.duration,
|
||||
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, {
|
||||
method: "PATCH",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
body: JSON.stringify({
|
||||
totalSize: body.totalSize.toString(),
|
||||
duration: body.duration.toString(),
|
||||
minPricePerBytePerSecond: body.minPricePerBytePerSecond.toString(),
|
||||
totalCollateral: body.totalCollateral.toString(),
|
||||
}),
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
if (res.error) {
|
||||
@ -174,7 +219,7 @@ export class CodexMarketplace {
|
||||
Api.config.prefix +
|
||||
`/sales/availability/${availabilityId}/reservations`;
|
||||
|
||||
return Fetch.safeJson<CodexReservation[]>(url, {
|
||||
return Fetch.safeJson<CodexReservationsResponse>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
@ -183,22 +228,47 @@ export class CodexMarketplace {
|
||||
/**
|
||||
* Returns list of purchase IDs
|
||||
*/
|
||||
async purchaseIds(): Promise<SafeValue<string[]>> {
|
||||
async purchaseIds(): Promise<SafeValue<CodexPurchaseIdsResponse>> {
|
||||
const url = this.url + Api.config.prefix + `/storage/purchases`;
|
||||
|
||||
return Fetch.safeJson<string[]>(url, {
|
||||
return Fetch.safeJson<CodexPurchaseIdsResponse>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
}
|
||||
|
||||
async purchases(): Promise<SafeValue<CodexPurchase[]>> {
|
||||
const url = this.url + Api.config.prefix + `/storage/purchases`;
|
||||
private transformPurchase(p: CodexPurchaseWithoutTypes): CodexPurchase {
|
||||
const purchase: CodexPurchase = {
|
||||
requestId: p.requestId,
|
||||
state: p.state,
|
||||
};
|
||||
|
||||
const res = await Fetch.safeJson<string[]>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
if (p.error) {
|
||||
purchase.error = p.error;
|
||||
}
|
||||
|
||||
if (!p.request) {
|
||||
return purchase;
|
||||
}
|
||||
|
||||
return {
|
||||
...purchase,
|
||||
request: {
|
||||
...p.request,
|
||||
ask: {
|
||||
...p.request.ask,
|
||||
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) {
|
||||
return res;
|
||||
@ -220,7 +290,6 @@ export class CodexMarketplace {
|
||||
state: "error",
|
||||
error: p.data.message,
|
||||
requestId: "",
|
||||
request: {} as CodexStorageRequest,
|
||||
} satisfies CodexPurchase)
|
||||
: p.data
|
||||
),
|
||||
@ -234,9 +303,15 @@ export class CodexMarketplace {
|
||||
const url =
|
||||
this.url + Api.config.prefix + `/storage/purchases/` + purchaseId;
|
||||
|
||||
return Fetch.safeJson<CodexPurchase>(url, {
|
||||
method: "GET",
|
||||
return Fetch.safeJson<CodexPurchaseResponse>(url, {
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
method: "GET",
|
||||
}).then((res) => {
|
||||
if (res.error) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return { error: false, data: this.transformPurchase(res.data) };
|
||||
});
|
||||
}
|
||||
|
||||
@ -269,24 +344,18 @@ export class CodexMarketplace {
|
||||
} = result.output;
|
||||
const url = this.url + Api.config.prefix + "/storage/request/" + cid;
|
||||
|
||||
const res = await Fetch.safe(url, {
|
||||
return Fetch.safeText(url, {
|
||||
method: "POST",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
body: JSON.stringify({
|
||||
duration: duration.toString(),
|
||||
duration,
|
||||
pricePerBytePerSecond: pricePerBytePerSecond.toString(),
|
||||
proofProbability: proofProbability.toString(),
|
||||
nodes,
|
||||
collateralPerByte: collateralPerByte.toString(),
|
||||
expiry: expiry.toString(),
|
||||
expiry,
|
||||
tolerance,
|
||||
}),
|
||||
} satisfies CodexStorageRequestCreateBody),
|
||||
});
|
||||
|
||||
if (res.error) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return { error: false, data: await res.data.text() };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,231 +1,121 @@
|
||||
import type { components, paths } from "../openapi";
|
||||
import * as v from "valibot";
|
||||
|
||||
export type CodexStorageRequest = {
|
||||
id: string;
|
||||
export type CodexSlotResponse =
|
||||
paths["/sales/slots"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
/**
|
||||
* Address of Ethereum address
|
||||
*/
|
||||
client: string;
|
||||
export type CodexSlot = CodexSlotResponse;
|
||||
|
||||
ask: {
|
||||
/**
|
||||
* Number of slots that the tequest want to have the content spread over.
|
||||
*/
|
||||
slots: number;
|
||||
export type CodexSlotAgentResponse =
|
||||
paths["/sales/slots/{slotId}"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
/**
|
||||
* Amount of storage per slot (in bytes) as decimal string.
|
||||
*/
|
||||
slotSize: string;
|
||||
export type CodexSlotAgent = CodexSlotAgentResponse;
|
||||
|
||||
/**
|
||||
* The duration of the storage request in seconds.
|
||||
*/
|
||||
duration: string;
|
||||
export type CodexAvailabilityResponse =
|
||||
paths["/sales/availability"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
/**
|
||||
* How often storage proofs are required as decimal string (in periods).
|
||||
*/
|
||||
proofProbability: string;
|
||||
export type CodexAvailabilityWithoutTypes =
|
||||
components["schemas"]["SalesAvailabilityREAD"];
|
||||
|
||||
/**
|
||||
* The amount of tokens paid per byte per second per slot to hosts the client is willing to pay
|
||||
*/
|
||||
pricePerBytePerSecond: string;
|
||||
|
||||
/**
|
||||
* Max slots that can be lost without data considered to be lost.
|
||||
*/
|
||||
maxSlotLoss: 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
|
||||
*/
|
||||
export type CodexAvailability = Omit<
|
||||
CodexAvailabilityWithoutTypes,
|
||||
| "freeSize"
|
||||
| "totalSize"
|
||||
| "minPricePerBytePerSecond"
|
||||
| "duration"
|
||||
| "totalCollateral"
|
||||
| "totalRemainingCollateral"
|
||||
> & {
|
||||
freeSize?: 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Total collateral (in amount of tokens) that can be used for matching requests
|
||||
*/
|
||||
totalCollateral: number;
|
||||
|
||||
totalRemainingCollateral: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Storage availability received from the api.
|
||||
*/
|
||||
export type CodexAvailabilityDto = {
|
||||
id: string;
|
||||
export type CodexAvailabilityCreateResponse =
|
||||
paths["/sales/availability"]["post"]["responses"][201]["content"]["application/json"];
|
||||
|
||||
/**
|
||||
* Size of available storage in bytes
|
||||
*/
|
||||
totalSize: string;
|
||||
|
||||
/**
|
||||
* 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 type CodexAvailabilityCreateBody = Exclude<
|
||||
paths["/sales/availability"]["post"]["requestBody"],
|
||||
undefined
|
||||
>["content"]["application/json"];
|
||||
|
||||
export const CodexCreateAvailabilityInput = v.strictObject({
|
||||
totalSize: v.pipe(v.number(), v.minValue(1)),
|
||||
duration: v.pipe(v.number(), v.minValue(1)),
|
||||
minPricePerBytePerSecond: 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<
|
||||
typeof CodexCreateAvailabilityInput
|
||||
>;
|
||||
|
||||
export const CodexUpdateAvailabilityInput = v.strictObject({
|
||||
export const CodexAvailabilityPatchInput = v.strictObject({
|
||||
id: v.string(),
|
||||
totalSize: v.pipe(v.number(), v.minValue(1)),
|
||||
duration: v.pipe(v.number(), v.minValue(1)),
|
||||
minPricePerBytePerSecond: v.number(),
|
||||
totalCollateral: v.number(),
|
||||
enabled: v.optional(v.boolean()),
|
||||
until: v.optional(v.number()),
|
||||
});
|
||||
|
||||
export type CodexUpdateAvailabilityInput = v.InferOutput<
|
||||
typeof CodexUpdateAvailabilityInput
|
||||
export type CodexAvailabilityPatchInput = v.InferOutput<
|
||||
typeof CodexAvailabilityPatchInput
|
||||
>;
|
||||
|
||||
export type CodexReservation = {
|
||||
id: string;
|
||||
availabilityId: string;
|
||||
requestId: string;
|
||||
export type CodexReservationsResponse =
|
||||
paths["/sales/availability/{id}/reservations"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
/**
|
||||
* Size in bytes
|
||||
*/
|
||||
size: string;
|
||||
export type CodexReservation = components["schemas"]["Reservation"];
|
||||
|
||||
/**
|
||||
* Slot Index as hexadecimal string
|
||||
*/
|
||||
slotIndex: string;
|
||||
export type CodexPurchaseIdsResponse =
|
||||
paths["/storage/purchases"]["get"]["responses"][200]["content"]["application/json"];
|
||||
|
||||
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 = {
|
||||
/**
|
||||
* Description of the request's state
|
||||
*/
|
||||
state: string;
|
||||
export type CodexPurchaseWithoutTypes = components["schemas"]["Purchase"];
|
||||
|
||||
/**
|
||||
* If request failed, then here is presented the error message
|
||||
*/
|
||||
error: string;
|
||||
|
||||
request: CodexStorageRequest;
|
||||
|
||||
requestId: string;
|
||||
export type CodexPurchase = Omit<
|
||||
components["schemas"]["Purchase"],
|
||||
"request"
|
||||
> & {
|
||||
request?: Omit<components["schemas"]["StorageRequest"], "ask"> & {
|
||||
ask: CodexStorageAsk;
|
||||
};
|
||||
};
|
||||
|
||||
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({
|
||||
cid: v.string(),
|
||||
|
||||
@ -5,7 +5,14 @@ import {
|
||||
type FetchAuth,
|
||||
} from "../fetch-safe/fetch-safe";
|
||||
import type { SafeValue } from "../values/values";
|
||||
import type { CodexSpr } from "./types";
|
||||
import type {
|
||||
CodexPeerId,
|
||||
CodexPeerIdContentType,
|
||||
CodexPeerIdJsonResponse,
|
||||
CodexSpr,
|
||||
CodexSprContentType,
|
||||
CodexSprJsonResponse,
|
||||
} from "./types";
|
||||
|
||||
type CodexNodeOptions = {
|
||||
auth?: FetchAuth;
|
||||
@ -25,9 +32,8 @@ export class CodexNode {
|
||||
|
||||
/**
|
||||
* Connect to a peer
|
||||
* TODO check result
|
||||
*/
|
||||
connect(peerId: string, addrs: string[] = []) {
|
||||
connect(peerId: string, addrs: string[] = []): Promise<SafeValue<string>> {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
for (const addr of addrs) {
|
||||
@ -37,7 +43,7 @@ export class CodexNode {
|
||||
const url =
|
||||
this.url + Api.config.prefix + `/connect/${peerId}?` + params.toString();
|
||||
|
||||
return Fetch.safe(url, {
|
||||
return Fetch.safeText(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
});
|
||||
@ -46,25 +52,54 @@ export class CodexNode {
|
||||
/**
|
||||
* 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";
|
||||
|
||||
return Fetch.safeJson(url, {
|
||||
if (type === "json") {
|
||||
return Fetch.safeJson<CodexSprJsonResponse>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
headers: {
|
||||
...FetchAuthBuilder.build(this.auth),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return Fetch.safeText(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
...FetchAuthBuilder.build(this.auth),
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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";
|
||||
|
||||
return Fetch.safe(url, {
|
||||
if (type === "json") {
|
||||
return Fetch.safeJson<CodexPeerIdJsonResponse>(url, {
|
||||
method: "GET",
|
||||
headers: FetchAuthBuilder.build(this.auth),
|
||||
headers: {
|
||||
...FetchAuthBuilder.build(this.auth),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return Fetch.safeText(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
...FetchAuthBuilder.build(this.auth),
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,29 @@
|
||||
export type CodexSpr = {
|
||||
spr: string;
|
||||
};
|
||||
import type { paths } from "../openapi";
|
||||
|
||||
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;
|
||||
|
||||
1449
src/openapi.ts
Normal file
1449
src/openapi.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"verbatimModuleSyntax": true,
|
||||
"sourceMap": true
|
||||
"sourceMap": true,
|
||||
"noUncheckedIndexedAccess": true
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user