mirror of
https://github.com/logos-storage/logos-storage-js.git
synced 2026-01-02 13:33:07 +00:00
Apply prettier format
This commit is contained in:
parent
ddb98b794a
commit
5e36ffb443
@ -1,10 +0,0 @@
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
indent_style = tab
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
18
package-lock.json
generated
18
package-lock.json
generated
@ -14,11 +14,12 @@
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"prettier": "^3.3.3",
|
||||
"tsup": "^8.2.3",
|
||||
"typescript": "^5.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
@ -1568,6 +1569,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
|
||||
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
|
||||
@ -9,11 +9,12 @@
|
||||
"scripts": {
|
||||
"prepack": "npm run build",
|
||||
"prebuild": "rm -Rf dist/*",
|
||||
"build": "tsup tsup src/index.ts --format esm,cjs --dts --minify",
|
||||
"build": "tsup tsup src/index.ts --format esm,cjs --dts",
|
||||
"compile": "tsc --noEmit",
|
||||
"pretest": "npm run build",
|
||||
"test": "node --test",
|
||||
"watch": "tsc --watch"
|
||||
"watch": "tsc --watch",
|
||||
"format": "prettier --write ./src"
|
||||
},
|
||||
"keywords": [
|
||||
"Codex",
|
||||
@ -48,10 +49,11 @@
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"prettier": "^3.3.3",
|
||||
"tsup": "^8.2.3",
|
||||
"typescript": "^5.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"valibot": "^0.36.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
prettier.config.cjs
Normal file
4
prettier.config.cjs
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
trailingComma: 'es5',
|
||||
bracketSameLine: true,
|
||||
};
|
||||
@ -1,5 +1,5 @@
|
||||
export const Api = {
|
||||
config: {
|
||||
prefix: "/api/codex/v1"
|
||||
}
|
||||
}
|
||||
config: {
|
||||
prefix: "/api/codex/v1",
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
import type { SafeValue } from "../values/values"
|
||||
import type { SafeValue } from "../values/values";
|
||||
|
||||
export class Disk {
|
||||
readonly url: string
|
||||
readonly url: string;
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url
|
||||
}
|
||||
constructor(url: string) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
async available(): Promise<SafeValue<{ full: number, used: number }>> {
|
||||
return {
|
||||
error: false,
|
||||
data: {
|
||||
full: 500,
|
||||
used: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
async available(): Promise<SafeValue<{ full: number; used: number }>> {
|
||||
return {
|
||||
error: false,
|
||||
data: {
|
||||
full: 500,
|
||||
used: 200,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +1,39 @@
|
||||
import { type InferIssue } from "valibot"
|
||||
import { type InferIssue } from "valibot";
|
||||
|
||||
type ValidationError = {
|
||||
expected: string
|
||||
received: string
|
||||
message: string
|
||||
path: string
|
||||
}
|
||||
expected: string;
|
||||
received: string;
|
||||
message: string;
|
||||
path: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* The CodexError which can be error object of 3 types:
|
||||
* `error`: Object containing the error message
|
||||
* `api`: Object containing the api error message and the status code
|
||||
* `validation`: Object containing the error message and a field `errors` of type ValidationError
|
||||
* containing the error message for each fields.
|
||||
* The CodexError which can be error object of 3 types:
|
||||
* `error`: Object containing the error message
|
||||
* `api`: Object containing the api error message and the status code
|
||||
* `validation`: Object containing the error message and a field `errors` of type ValidationError
|
||||
* containing the error message for each fields.
|
||||
*/
|
||||
export type CodexError = {
|
||||
type: "error"
|
||||
message: string
|
||||
} | {
|
||||
type: "api"
|
||||
message: string
|
||||
status: number
|
||||
} | {
|
||||
type: "validation"
|
||||
message: string
|
||||
errors: ValidationError[]
|
||||
}
|
||||
|
||||
export const CodexValibotIssuesMap = (issues: InferIssue<any>[]) => issues.map(i => ({
|
||||
expected: i.expected,
|
||||
received: i.received,
|
||||
message: i.message,
|
||||
path: i.path.map((item: { key: string }) => item.key).join('.')
|
||||
}))
|
||||
|
||||
export type CodexError =
|
||||
| {
|
||||
type: "error";
|
||||
message: string;
|
||||
}
|
||||
| {
|
||||
type: "api";
|
||||
message: string;
|
||||
status: number;
|
||||
}
|
||||
| {
|
||||
type: "validation";
|
||||
message: string;
|
||||
errors: ValidationError[];
|
||||
};
|
||||
|
||||
export const CodexValibotIssuesMap = (issues: InferIssue<any>[]) =>
|
||||
issues.map((i) => ({
|
||||
expected: i.expected,
|
||||
received: i.received,
|
||||
message: i.message,
|
||||
path: i.path.map((item: { key: string }) => item.key).join("."),
|
||||
}));
|
||||
|
||||
@ -1,88 +1,95 @@
|
||||
import assert from "assert";
|
||||
import { describe, it } from "node:test";
|
||||
import { Fetch } from '../fetch-safe/fetch-safe';
|
||||
import { Fetch } from "../fetch-safe/fetch-safe";
|
||||
|
||||
class MockResponse implements Response {
|
||||
headers: Headers = new Headers()
|
||||
ok: boolean;
|
||||
redirected = false
|
||||
status: number;
|
||||
statusText = "";
|
||||
type = "basic" as "basic"
|
||||
url = ""
|
||||
body = null;
|
||||
bodyUsed = false;
|
||||
_text: string
|
||||
headers: Headers = new Headers();
|
||||
ok: boolean;
|
||||
redirected = false;
|
||||
status: number;
|
||||
statusText = "";
|
||||
type = "basic" as "basic";
|
||||
url = "";
|
||||
body = null;
|
||||
bodyUsed = false;
|
||||
_text: string;
|
||||
|
||||
constructor(ok: boolean, status: number, text: string) {
|
||||
this.ok = ok
|
||||
this.status = status
|
||||
this._text = text
|
||||
}
|
||||
constructor(ok: boolean, status: number, text: string) {
|
||||
this.ok = ok;
|
||||
this.status = status;
|
||||
this._text = text;
|
||||
}
|
||||
|
||||
clone(): Response {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
clone(): Response {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
arrayBuffer(): Promise<ArrayBuffer> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
arrayBuffer(): Promise<ArrayBuffer> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
blob(): Promise<Blob> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
blob(): Promise<Blob> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
formData(): Promise<FormData> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
formData(): Promise<FormData> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
json(): Promise<any> {
|
||||
return Promise.resolve(JSON.parse(this._text))
|
||||
}
|
||||
json(): Promise<any> {
|
||||
return Promise.resolve(JSON.parse(this._text));
|
||||
}
|
||||
|
||||
text(): Promise<string> {
|
||||
return Promise.resolve(this._text)
|
||||
}
|
||||
text(): Promise<string> {
|
||||
return Promise.resolve(this._text);
|
||||
}
|
||||
}
|
||||
|
||||
describe("fetch", () => {
|
||||
it("returns an error when the http call failed", async (t) => {
|
||||
global.fetch = t.mock.fn(() =>
|
||||
Promise.resolve(new MockResponse(false, 500, "error")),
|
||||
);
|
||||
it("returns an error when the http call failed", async (t) => {
|
||||
global.fetch = t.mock.fn(() =>
|
||||
Promise.resolve(new MockResponse(false, 500, "error"))
|
||||
);
|
||||
|
||||
const result = await Fetch.safe("http://localhost:3000/some-url", { method: "GET" })
|
||||
const error = {
|
||||
type: "api",
|
||||
message: "error",
|
||||
status: 500
|
||||
}
|
||||
const result = await Fetch.safe("http://localhost:3000/some-url", {
|
||||
method: "GET",
|
||||
});
|
||||
const error = {
|
||||
type: "api",
|
||||
message: "error",
|
||||
status: 500,
|
||||
};
|
||||
|
||||
assert.deepStrictEqual(result, { error: true, data: error });
|
||||
assert.deepStrictEqual(result, { error: true, data: error });
|
||||
});
|
||||
|
||||
it("returns an error when the json parsing failed", async (t) => {
|
||||
global.fetch = t.mock.fn(() =>
|
||||
Promise.resolve(new MockResponse(true, 200, ""))
|
||||
);
|
||||
|
||||
const result = await Fetch.safe("http://localhost:3000/some-url", {
|
||||
method: "GET",
|
||||
});
|
||||
const error = {
|
||||
type: "error",
|
||||
message: "Unexpected end of JSON input",
|
||||
};
|
||||
|
||||
assert.deepStrictEqual(result, { error: true, data: error });
|
||||
});
|
||||
|
||||
it("returns the data when the fetch succeed", async (t) => {
|
||||
global.fetch = t.mock.fn(() =>
|
||||
Promise.resolve(
|
||||
new MockResponse(true, 200, JSON.stringify({ hello: "world" }))
|
||||
)
|
||||
);
|
||||
|
||||
const result = await Fetch.safe("http://localhost:3000/some-url", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
it("returns an error when the json parsing failed", async (t) => {
|
||||
global.fetch = t.mock.fn(() =>
|
||||
Promise.resolve(new MockResponse(true, 200, "")),
|
||||
);
|
||||
|
||||
const result = await Fetch.safe("http://localhost:3000/some-url", { method: "GET" })
|
||||
const error = {
|
||||
type: "error",
|
||||
message: "Unexpected end of JSON input"
|
||||
}
|
||||
|
||||
assert.deepStrictEqual(result, { error: true, data: error });
|
||||
});
|
||||
|
||||
|
||||
it("returns the data when the fetch succeed", async (t) => {
|
||||
global.fetch = t.mock.fn(() =>
|
||||
Promise.resolve(new MockResponse(true, 200, JSON.stringify({ hello: "world" }))),
|
||||
);
|
||||
|
||||
const result = await Fetch.safe("http://localhost:3000/some-url", { method: "GET" })
|
||||
|
||||
assert.deepStrictEqual(result, { error: false, data: { hello: "world" } });
|
||||
});
|
||||
assert.deepStrictEqual(result, { error: false, data: { hello: "world" } });
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,34 +1,37 @@
|
||||
import { type SafeValue } from "../values/values"
|
||||
import { type SafeValue } from "../values/values";
|
||||
|
||||
export const Fetch = {
|
||||
async safe<T extends Object>(url: string, init: RequestInit): Promise<SafeValue<T>> {
|
||||
const res = await fetch(url, init)
|
||||
async safe<T extends Object>(
|
||||
url: string,
|
||||
init: RequestInit
|
||||
): Promise<SafeValue<T>> {
|
||||
const res = await fetch(url, init);
|
||||
|
||||
if (!res.ok) {
|
||||
const message = await res.text()
|
||||
if (!res.ok) {
|
||||
const message = await res.text();
|
||||
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "api",
|
||||
message,
|
||||
status: res.status
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "api",
|
||||
message,
|
||||
status: res.status,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const json = await res.json()
|
||||
try {
|
||||
const json = await res.json();
|
||||
|
||||
return { error: false, data: json }
|
||||
} catch (e) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "error",
|
||||
message: e instanceof Error ? e.message : "JSON parsing error :" + e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { error: false, data: json };
|
||||
} catch (e) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "error",
|
||||
message: e instanceof Error ? e.message : "JSON parsing error :" + e,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
33
src/index.ts
33
src/index.ts
@ -5,26 +5,25 @@ export * from "./fetch-safe/fetch-safe";
|
||||
export * from "./marketplace/types";
|
||||
|
||||
export class Codex {
|
||||
readonly url: string
|
||||
private _marketplace: Marketplace | null
|
||||
readonly disk: Disk
|
||||
readonly url: string;
|
||||
private _marketplace: Marketplace | null;
|
||||
readonly disk: Disk;
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url
|
||||
this._marketplace = null
|
||||
this.disk = new Disk(url)
|
||||
}
|
||||
constructor(url: string) {
|
||||
this.url = url;
|
||||
this._marketplace = null;
|
||||
this.disk = new Disk(url);
|
||||
}
|
||||
|
||||
async marketplace() {
|
||||
if (this._marketplace) {
|
||||
return this._marketplace
|
||||
}
|
||||
async marketplace() {
|
||||
if (this._marketplace) {
|
||||
return this._marketplace;
|
||||
}
|
||||
|
||||
const module = await import("./marketplace/marketplace")
|
||||
const module = await import("./marketplace/marketplace");
|
||||
|
||||
this._marketplace = new module.Marketplace(this.url)
|
||||
this._marketplace = new module.Marketplace(this.url);
|
||||
|
||||
return module.Marketplace
|
||||
}
|
||||
return module.Marketplace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -36,343 +36,354 @@ import { Marketplace } from "./marketplace";
|
||||
// }
|
||||
|
||||
function createStorageRequest() {
|
||||
return {
|
||||
cid: faker.string.alphanumeric(64),
|
||||
duration: faker.number.int({ min: 1 }),
|
||||
reward: faker.number.int(),
|
||||
proofProbability: faker.number.int(),
|
||||
nodes: faker.number.int(),
|
||||
tolerance: faker.number.int(),
|
||||
expiry: faker.number.int({ min: 1 }),
|
||||
collateral: faker.number.int()
|
||||
}
|
||||
return {
|
||||
cid: faker.string.alphanumeric(64),
|
||||
duration: faker.number.int({ min: 1 }),
|
||||
reward: faker.number.int(),
|
||||
proofProbability: faker.number.int(),
|
||||
nodes: faker.number.int(),
|
||||
tolerance: faker.number.int(),
|
||||
expiry: faker.number.int({ min: 1 }),
|
||||
collateral: faker.number.int(),
|
||||
};
|
||||
}
|
||||
|
||||
function missingNumberValidationError(field: string) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: 'number',
|
||||
message: 'Invalid type: Expected number but received undefined',
|
||||
received: 'undefined'
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: "number",
|
||||
message: "Invalid type: Expected number but received undefined",
|
||||
received: "undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function extraValidationError(field: string, value: unknown) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: 'never',
|
||||
message: `Invalid type: Expected never but received "${value}"`,
|
||||
received: `"${value}"`
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: "never",
|
||||
message: `Invalid type: Expected never but received "${value}"`,
|
||||
received: `"${value}"`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function missingStringValidationError(field: string) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: 'string',
|
||||
message: 'Invalid type: Expected string but received undefined',
|
||||
received: 'undefined'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: "string",
|
||||
message: "Invalid type: Expected string but received undefined",
|
||||
received: "undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function mistypeNumberValidationError(field: string, value: string) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: 'number',
|
||||
message: `Invalid type: Expected number but received "${value}"`,
|
||||
received: `"${value}"`
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: "number",
|
||||
message: `Invalid type: Expected number but received "${value}"`,
|
||||
received: `"${value}"`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function minNumberValidationError(field: string, min: number) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: '>=' + min,
|
||||
message: 'Invalid value: Expected >=1 but received 0',
|
||||
received: '0'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: [
|
||||
{
|
||||
path: field,
|
||||
expected: ">=" + min,
|
||||
message: "Invalid value: Expected >=1 but received 0",
|
||||
received: "0",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createAvailability() {
|
||||
return {
|
||||
"id": faker.finance.ethereumAddress(),
|
||||
"availabilityId": faker.finance.ethereumAddress(),
|
||||
"size": faker.number.int({ min: 3000, max: 300000 }),
|
||||
"requestId": faker.finance.ethereumAddress(),
|
||||
"slotIndex": faker.number.int({ min: 0, max: 9 })
|
||||
}
|
||||
return {
|
||||
id: faker.finance.ethereumAddress(),
|
||||
availabilityId: faker.finance.ethereumAddress(),
|
||||
size: faker.number.int({ min: 3000, max: 300000 }),
|
||||
requestId: faker.finance.ethereumAddress(),
|
||||
slotIndex: faker.number.int({ min: 0, max: 9 }),
|
||||
};
|
||||
}
|
||||
|
||||
describe("marketplace", () => {
|
||||
const marketplace = new Marketplace("http://localhost:3000")
|
||||
const marketplace = new Marketplace("http://localhost:3000");
|
||||
|
||||
it("returns an error when trying to create an availability without total size", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
} as any)
|
||||
it("returns an error when trying to create an availability without total size", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
} as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("totalSize"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("totalSize"));
|
||||
});
|
||||
|
||||
it.only("returns an error when trying to create an availability with an invalid number valid", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
totalSize: "abc"
|
||||
} as any)
|
||||
it.only("returns an error when trying to create an availability with an invalid number valid", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
totalSize: "abc",
|
||||
} as any);
|
||||
|
||||
assert.deepStrictEqual(response, mistypeNumberValidationError("totalSize", "abc"));
|
||||
});
|
||||
assert.deepStrictEqual(
|
||||
response,
|
||||
mistypeNumberValidationError("totalSize", "abc")
|
||||
);
|
||||
});
|
||||
|
||||
it("returns an error when trying to create an availability with zero total size", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
totalSize: 0
|
||||
})
|
||||
it("returns an error when trying to create an availability with zero total size", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
totalSize: 0,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, minNumberValidationError("totalSize", 1))
|
||||
});
|
||||
assert.deepStrictEqual(response, minNumberValidationError("totalSize", 1));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create an availability without duration", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
totalSize: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
} as any)
|
||||
it("returns an error when trying to create an availability without duration", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
totalSize: 3000,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
} as any);
|
||||
|
||||
console.info(response.error)
|
||||
console.info(response.error);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("duration"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("duration"));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create an availability with zero duration", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 0,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
totalSize: 3000
|
||||
})
|
||||
it("returns an error when trying to create an availability with zero duration", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
duration: 0,
|
||||
maxCollateral: 1,
|
||||
minPrice: 100,
|
||||
totalSize: 3000,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, minNumberValidationError("duration", 1))
|
||||
});
|
||||
assert.deepStrictEqual(response, minNumberValidationError("duration", 1));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create an availability without min price", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
totalSize: 3000,
|
||||
maxCollateral: 1,
|
||||
duration: 100,
|
||||
} as any)
|
||||
it("returns an error when trying to create an availability without min price", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
totalSize: 3000,
|
||||
maxCollateral: 1,
|
||||
duration: 100,
|
||||
} as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("minPrice"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("minPrice"));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create an availability without max collateral", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
} as any)
|
||||
it("returns an error when trying to create an availability without max collateral", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
} as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("maxCollateral"));
|
||||
});
|
||||
assert.deepStrictEqual(
|
||||
response,
|
||||
missingNumberValidationError("maxCollateral")
|
||||
);
|
||||
});
|
||||
|
||||
it("returns an error when trying to create an availability with an extra field", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
maxCollateral: 1,
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
hello: "world"
|
||||
} as any)
|
||||
it("returns an error when trying to create an availability with an extra field", async () => {
|
||||
const response = await marketplace.createAvailability({
|
||||
maxCollateral: 1,
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
hello: "world",
|
||||
} as any);
|
||||
|
||||
assert.deepStrictEqual(response, extraValidationError("hello", "world"));
|
||||
});
|
||||
assert.deepStrictEqual(response, extraValidationError("hello", "world"));
|
||||
});
|
||||
|
||||
it("returns a response when the request succeed", async (t) => {
|
||||
const data = { ...createAvailability(), freeSize: 1000 }
|
||||
it("returns a response when the request succeed", async (t) => {
|
||||
const data = { ...createAvailability(), freeSize: 1000 };
|
||||
|
||||
t.mock.method(Fetch, "safe", () =>
|
||||
Promise.resolve({ error: false, data }),
|
||||
);
|
||||
t.mock.method(Fetch, "safe", () => Promise.resolve({ error: false, data }));
|
||||
|
||||
const response = await marketplace.createAvailability({
|
||||
maxCollateral: 1,
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
})
|
||||
const response = await marketplace.createAvailability({
|
||||
maxCollateral: 1,
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, { error: false, data });
|
||||
});
|
||||
assert.deepStrictEqual(response, { error: false, data });
|
||||
});
|
||||
|
||||
it("returns a response when the create availability succeed", async (t) => {
|
||||
const data = { ...createAvailability(), freeSize: 1000 }
|
||||
it("returns a response when the create availability succeed", async (t) => {
|
||||
const data = { ...createAvailability(), freeSize: 1000 };
|
||||
|
||||
t.mock.method(Fetch, "safe", () =>
|
||||
Promise.resolve({ error: false, data }),
|
||||
);
|
||||
t.mock.method(Fetch, "safe", () => Promise.resolve({ error: false, data }));
|
||||
|
||||
const response = await marketplace.createAvailability({
|
||||
maxCollateral: 1,
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
})
|
||||
const response = await marketplace.createAvailability({
|
||||
maxCollateral: 1,
|
||||
totalSize: 3000,
|
||||
minPrice: 100,
|
||||
duration: 100,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, { error: false, data });
|
||||
});
|
||||
assert.deepStrictEqual(response, { error: false, data });
|
||||
});
|
||||
|
||||
it("returns an error when trying to update an availability without id", async () => {
|
||||
const response = await marketplace.updateAvailability({
|
||||
} as any)
|
||||
it("returns an error when trying to update an availability without id", async () => {
|
||||
const response = await marketplace.updateAvailability({} as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingStringValidationError("id"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingStringValidationError("id"));
|
||||
});
|
||||
|
||||
it("returns an error when trying to update an availability with zero total size", async () => {
|
||||
const response = await marketplace.updateAvailability({
|
||||
id: faker.string.alphanumeric(64),
|
||||
totalSize: 0
|
||||
})
|
||||
it("returns an error when trying to update an availability with zero total size", async () => {
|
||||
const response = await marketplace.updateAvailability({
|
||||
id: faker.string.alphanumeric(64),
|
||||
totalSize: 0,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, minNumberValidationError("totalSize", 1))
|
||||
});
|
||||
assert.deepStrictEqual(response, minNumberValidationError("totalSize", 1));
|
||||
});
|
||||
|
||||
it("returns an error when trying to update an availability with zero duration", async () => {
|
||||
const response = await marketplace.updateAvailability({
|
||||
id: faker.string.alphanumeric(64),
|
||||
duration: 0
|
||||
})
|
||||
it("returns an error when trying to update an availability with zero duration", async () => {
|
||||
const response = await marketplace.updateAvailability({
|
||||
id: faker.string.alphanumeric(64),
|
||||
duration: 0,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, minNumberValidationError("duration", 1))
|
||||
});
|
||||
assert.deepStrictEqual(response, minNumberValidationError("duration", 1));
|
||||
});
|
||||
|
||||
it("returns a response when the update availability succeed", async (t) => {
|
||||
const data = createAvailability()
|
||||
it("returns a response when the update availability succeed", async (t) => {
|
||||
const data = createAvailability();
|
||||
|
||||
t.mock.method(Fetch, "safe", () =>
|
||||
Promise.resolve({ error: false, data }),
|
||||
);
|
||||
t.mock.method(Fetch, "safe", () => Promise.resolve({ error: false, data }));
|
||||
|
||||
const response = await marketplace.updateAvailability({
|
||||
id: faker.string.alphanumeric(64),
|
||||
totalSize: 3000,
|
||||
})
|
||||
const response = await marketplace.updateAvailability({
|
||||
id: faker.string.alphanumeric(64),
|
||||
totalSize: 3000,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, { error: false, data });
|
||||
});
|
||||
assert.deepStrictEqual(response, { error: false, data });
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request without cid", async () => {
|
||||
const { cid, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request without cid", async () => {
|
||||
const { cid, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest(rest as any)
|
||||
const response = await marketplace.createStorageRequest(rest as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingStringValidationError("cid"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingStringValidationError("cid"));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request without duration", async () => {
|
||||
const { duration, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request without duration", async () => {
|
||||
const { duration, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest(rest as any)
|
||||
const response = await marketplace.createStorageRequest(rest as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("duration"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("duration"));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request with zero duration", async () => {
|
||||
const { duration, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request with zero duration", async () => {
|
||||
const { duration, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest({ ...rest, duration: 0 })
|
||||
const response = await marketplace.createStorageRequest({
|
||||
...rest,
|
||||
duration: 0,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, minNumberValidationError("duration", 1));
|
||||
});
|
||||
assert.deepStrictEqual(response, minNumberValidationError("duration", 1));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request without reward", async () => {
|
||||
const { reward, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request without reward", async () => {
|
||||
const { reward, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest(rest as any)
|
||||
const response = await marketplace.createStorageRequest(rest as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("reward"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("reward"));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request without proof probability", async () => {
|
||||
const { proofProbability, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request without proof probability", async () => {
|
||||
const { proofProbability, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest(rest as any)
|
||||
const response = await marketplace.createStorageRequest(rest as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("proofProbability"));
|
||||
});
|
||||
assert.deepStrictEqual(
|
||||
response,
|
||||
missingNumberValidationError("proofProbability")
|
||||
);
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request without expiry", async () => {
|
||||
const { expiry, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request without expiry", async () => {
|
||||
const { expiry, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest(rest as any)
|
||||
const response = await marketplace.createStorageRequest(rest as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("expiry"));
|
||||
});
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("expiry"));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request with zero expiry", async () => {
|
||||
const { expiry, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request with zero expiry", async () => {
|
||||
const { expiry, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest({ ...rest, expiry: 0 })
|
||||
const response = await marketplace.createStorageRequest({
|
||||
...rest,
|
||||
expiry: 0,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(response, minNumberValidationError("expiry", 1));
|
||||
});
|
||||
assert.deepStrictEqual(response, minNumberValidationError("expiry", 1));
|
||||
});
|
||||
|
||||
it("returns an error when trying to create a storage request without collateral", async () => {
|
||||
const { collateral, ...rest } = createStorageRequest()
|
||||
it("returns an error when trying to create a storage request without collateral", async () => {
|
||||
const { collateral, ...rest } = createStorageRequest();
|
||||
|
||||
const response = await marketplace.createStorageRequest(rest as any)
|
||||
const response = await marketplace.createStorageRequest(rest as any);
|
||||
|
||||
assert.deepStrictEqual(response, missingNumberValidationError("collateral"));
|
||||
});
|
||||
assert.deepStrictEqual(
|
||||
response,
|
||||
missingNumberValidationError("collateral")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,167 +1,189 @@
|
||||
import * as v from 'valibot'
|
||||
import { Api } from "../api/config"
|
||||
import { CodexValibotIssuesMap } from '../errors/errors'
|
||||
import { Fetch } from "../fetch-safe/fetch-safe"
|
||||
import type { SafeValue } from "../values/values"
|
||||
import { type CodexAvailability, type CodexAvailabilityCreateResponse, CodexCreateAvailabilityInput, CodexCreateStorageRequestInput, type CodexCreateStorageRequestResponse, type CodexPurchase, type CodexReservation, type CodexSlot, CodexUpdateAvailabilityInput } from "./types"
|
||||
import * as v from "valibot";
|
||||
import { Api } from "../api/config";
|
||||
import { CodexValibotIssuesMap } from "../errors/errors";
|
||||
import { Fetch } from "../fetch-safe/fetch-safe";
|
||||
import type { SafeValue } from "../values/values";
|
||||
import {
|
||||
type CodexAvailability,
|
||||
type CodexAvailabilityCreateResponse,
|
||||
CodexCreateAvailabilityInput,
|
||||
CodexCreateStorageRequestInput,
|
||||
type CodexCreateStorageRequestResponse,
|
||||
type CodexPurchase,
|
||||
type CodexReservation,
|
||||
type CodexSlot,
|
||||
CodexUpdateAvailabilityInput,
|
||||
} from "./types";
|
||||
|
||||
export class Marketplace {
|
||||
readonly url: string
|
||||
readonly url: string;
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url
|
||||
}
|
||||
constructor(url: string) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns active slots
|
||||
*/
|
||||
async activeSlots(): Promise<SafeValue<CodexSlot[]>> {
|
||||
const url = this.url + Api.config.prefix + "/sales/slots"
|
||||
/**
|
||||
* Returns active slots
|
||||
*/
|
||||
async activeSlots(): Promise<SafeValue<CodexSlot[]>> {
|
||||
const url = this.url + Api.config.prefix + "/sales/slots";
|
||||
|
||||
return Fetch.safe<CodexSlot[]>(url, {
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexSlot[]>(url, {
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns active slot with id {slotId} for the host
|
||||
*/
|
||||
async activeSlot(slotId: string): Promise<SafeValue<CodexSlot>> {
|
||||
const url = this.url + Api.config.prefix + "/sales/slots/" + slotId
|
||||
/**
|
||||
* Returns active slot with id {slotId} for the host
|
||||
*/
|
||||
async activeSlot(slotId: string): Promise<SafeValue<CodexSlot>> {
|
||||
const url = this.url + Api.config.prefix + "/sales/slots/" + slotId;
|
||||
|
||||
return Fetch.safe<CodexSlot>(url, {
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexSlot>(url, {
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns storage that is for sale
|
||||
*/
|
||||
async availabilities(): Promise<SafeValue<CodexAvailability[]>> {
|
||||
const url = this.url + Api.config.prefix + "/sales/availability"
|
||||
/**
|
||||
* Returns storage that is for sale
|
||||
*/
|
||||
async availabilities(): Promise<SafeValue<CodexAvailability[]>> {
|
||||
const url = this.url + Api.config.prefix + "/sales/availability";
|
||||
|
||||
return Fetch.safe<CodexAvailability[]>(url, {
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexAvailability[]>(url, {
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Offers storage for sale
|
||||
*/
|
||||
async createAvailability(input: CodexCreateAvailabilityInput)
|
||||
: Promise<SafeValue<CodexAvailabilityCreateResponse>> {
|
||||
const result = v.safeParse(CodexCreateAvailabilityInput, input)
|
||||
/**
|
||||
* Offers storage for sale
|
||||
*/
|
||||
async createAvailability(
|
||||
input: CodexCreateAvailabilityInput,
|
||||
): Promise<SafeValue<CodexAvailabilityCreateResponse>> {
|
||||
const result = v.safeParse(CodexCreateAvailabilityInput, input);
|
||||
|
||||
if (!result.success) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: CodexValibotIssuesMap(result.issues)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result.success) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: CodexValibotIssuesMap(result.issues),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const url = this.url + Api.config.prefix + "/sales/availability"
|
||||
const url = this.url + Api.config.prefix + "/sales/availability";
|
||||
|
||||
return Fetch.safe<CodexAvailabilityCreateResponse>(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(result.output)
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexAvailabilityCreateResponse>(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(result.output),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The new parameters will be only considered for new requests.
|
||||
* Existing Requests linked to this Availability will continue as is.
|
||||
*/
|
||||
async updateAvailability(input: CodexUpdateAvailabilityInput): Promise<SafeValue<CodexAvailability>> {
|
||||
const result = v.safeParse(CodexUpdateAvailabilityInput, input)
|
||||
/**
|
||||
* The new parameters will be only considered for new requests.
|
||||
* Existing Requests linked to this Availability will continue as is.
|
||||
*/
|
||||
async updateAvailability(
|
||||
input: CodexUpdateAvailabilityInput,
|
||||
): Promise<SafeValue<CodexAvailability>> {
|
||||
const result = v.safeParse(CodexUpdateAvailabilityInput, input);
|
||||
|
||||
if (!result.success) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: CodexValibotIssuesMap(result.issues)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result.success) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: CodexValibotIssuesMap(result.issues),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const url = this.url + Api.config.prefix + "/sales/availability/" + result.output.id
|
||||
const url =
|
||||
this.url + Api.config.prefix + "/sales/availability/" + result.output.id;
|
||||
|
||||
return Fetch.safe<CodexAvailability>(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(result.output)
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexAvailability>(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(result.output),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return's list of Reservations for ongoing Storage Requests that the node hosts.
|
||||
*/
|
||||
async reservations(availabilityId: string): Promise<SafeValue<CodexReservation[]>> {
|
||||
const url = this.url + Api.config.prefix + `/sales/availability/${availabilityId}/reservations`
|
||||
/**
|
||||
* Return's list of Reservations for ongoing Storage Requests that the node hosts.
|
||||
*/
|
||||
async reservations(
|
||||
availabilityId: string,
|
||||
): Promise<SafeValue<CodexReservation[]>> {
|
||||
const url =
|
||||
this.url +
|
||||
Api.config.prefix +
|
||||
`/sales/availability/${availabilityId}/reservations`;
|
||||
|
||||
return Fetch.safe<CodexReservation[]>(url, {
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexReservation[]>(url, {
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of purchase IDs
|
||||
*/
|
||||
async purchaseIds(): Promise<SafeValue<string[]>> {
|
||||
const url = this.url + Api.config.prefix + `/storage/purchases`
|
||||
/**
|
||||
* Returns list of purchase IDs
|
||||
*/
|
||||
async purchaseIds(): Promise<SafeValue<string[]>> {
|
||||
const url = this.url + Api.config.prefix + `/storage/purchases`;
|
||||
|
||||
return Fetch.safe<string[]>(url, {
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
return Fetch.safe<string[]>(url, {
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns purchase details
|
||||
*/
|
||||
async purchaseDetail(purchaseId: string): Promise<SafeValue<CodexPurchase>> {
|
||||
const url = this.url + Api.config.prefix + `/storage/purchases/` + purchaseId
|
||||
/**
|
||||
* Returns purchase details
|
||||
*/
|
||||
async purchaseDetail(purchaseId: string): Promise<SafeValue<CodexPurchase>> {
|
||||
const url =
|
||||
this.url + Api.config.prefix + `/storage/purchases/` + purchaseId;
|
||||
|
||||
return Fetch.safe<CodexPurchase>(url, {
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexPurchase>(url, {
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new request for storage.
|
||||
*/
|
||||
async createStorageRequest(input: CodexCreateStorageRequestInput): Promise<SafeValue<CodexCreateStorageRequestResponse>> {
|
||||
const result = v.safeParse(CodexCreateStorageRequestInput, input)
|
||||
/**
|
||||
* Creates a new request for storage.
|
||||
*/
|
||||
async createStorageRequest(
|
||||
input: CodexCreateStorageRequestInput,
|
||||
): Promise<SafeValue<CodexCreateStorageRequestResponse>> {
|
||||
const result = v.safeParse(CodexCreateStorageRequestInput, input);
|
||||
|
||||
if (!result.success) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: CodexValibotIssuesMap(result.issues)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result.success) {
|
||||
return {
|
||||
error: true,
|
||||
data: {
|
||||
type: "validation",
|
||||
message: "Cannot validate the input",
|
||||
errors: CodexValibotIssuesMap(result.issues),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const { cid, ...body } = result.output
|
||||
const url = this.url + Api.config.prefix + "/storage/request/" + cid
|
||||
const { cid, ...body } = result.output;
|
||||
const url = this.url + Api.config.prefix + "/storage/request/" + cid;
|
||||
|
||||
return Fetch.safe<CodexCreateStorageRequestResponse>(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
}
|
||||
return Fetch.safe<CodexCreateStorageRequestResponse>(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,195 +1,204 @@
|
||||
import * as v from 'valibot';
|
||||
import * as v from "valibot";
|
||||
|
||||
export type CodexStorageRequest = {
|
||||
id: string
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Address of Ethereum address
|
||||
*/
|
||||
client: string
|
||||
/**
|
||||
* Address of Ethereum address
|
||||
*/
|
||||
client: string;
|
||||
|
||||
ask: {
|
||||
/**
|
||||
* Number of slots that the tequest want to have the content spread over.
|
||||
*/
|
||||
slots: number
|
||||
ask: {
|
||||
/**
|
||||
* Number of slots that the tequest want to have the content spread over.
|
||||
*/
|
||||
slots: number;
|
||||
|
||||
/**
|
||||
* Amount of storage per slot (in bytes) as decimal string.
|
||||
*/
|
||||
slotSize: string
|
||||
/**
|
||||
* Amount of storage per slot (in bytes) as decimal string.
|
||||
*/
|
||||
slotSize: string;
|
||||
|
||||
/**
|
||||
* The duration of the storage request in seconds.
|
||||
*/
|
||||
duration: string
|
||||
/**
|
||||
* The duration of the storage request in seconds.
|
||||
*/
|
||||
duration: string;
|
||||
|
||||
/**
|
||||
* How often storage proofs are required as decimal string (in periods).
|
||||
*/
|
||||
proofProbability: string
|
||||
/**
|
||||
* How often storage proofs are required as decimal string (in periods).
|
||||
*/
|
||||
proofProbability: string;
|
||||
|
||||
/**
|
||||
* The maximum amount of tokens paid per second per slot to hosts
|
||||
* the client is willing to pay.
|
||||
*/
|
||||
reward: string
|
||||
/**
|
||||
* The maximum amount of tokens paid per second per slot to hosts
|
||||
* the client is willing to pay.
|
||||
*/
|
||||
reward: string;
|
||||
|
||||
/**
|
||||
* Max slots that can be lost without data considered to be lost.
|
||||
*/
|
||||
maxSlotLoss: number
|
||||
},
|
||||
/**
|
||||
* Max slots that can be lost without data considered to be lost.
|
||||
*/
|
||||
maxSlotLoss: number;
|
||||
};
|
||||
|
||||
content: {
|
||||
/**
|
||||
* Unique Content ID
|
||||
*/
|
||||
cid: string
|
||||
content: {
|
||||
/**
|
||||
* Unique Content ID
|
||||
*/
|
||||
cid: string;
|
||||
|
||||
/**
|
||||
* Erasure code parameters
|
||||
*/
|
||||
erasure: {
|
||||
/**
|
||||
* Total number of chunks generated by the erasure code process.
|
||||
*/
|
||||
totalChunks: number
|
||||
},
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 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,
|
||||
/* 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
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
id: string;
|
||||
|
||||
request: CodexStorageRequest,
|
||||
request: CodexStorageRequest;
|
||||
|
||||
/**
|
||||
* The slot index as hexadecimal string
|
||||
*/
|
||||
slotIndex: "string"
|
||||
}
|
||||
/**
|
||||
* The slot index as hexadecimal string
|
||||
*/
|
||||
slotIndex: "string";
|
||||
};
|
||||
|
||||
/**
|
||||
* Storage availability for sell.
|
||||
*/
|
||||
export type CodexAvailability = {
|
||||
id: string
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Size of available storage in bytes
|
||||
*/
|
||||
totalSize: string
|
||||
/**
|
||||
* Size of available storage in bytes
|
||||
*/
|
||||
totalSize: string;
|
||||
|
||||
/**
|
||||
* Maximum time the storage should be sold for (in seconds)
|
||||
*/
|
||||
duration: string
|
||||
/**
|
||||
* Maximum time the storage should be sold for (in seconds)
|
||||
*/
|
||||
duration: string;
|
||||
|
||||
/**
|
||||
* Minimum price to be paid (in amount of tokens)
|
||||
*/
|
||||
minPrice: string
|
||||
/**
|
||||
* Minimum price to be paid (in amount of tokens)
|
||||
*/
|
||||
minPrice: string;
|
||||
|
||||
/**
|
||||
* Maximum collateral user is willing to pay per filled Slot (in amount of tokens)
|
||||
*/
|
||||
maxCollateral: string
|
||||
}
|
||||
/**
|
||||
* Maximum collateral user is willing to pay per filled Slot (in amount of tokens)
|
||||
*/
|
||||
maxCollateral: string;
|
||||
};
|
||||
|
||||
export type CodexAvailabilityCreateResponse = CodexAvailability & {
|
||||
id: string
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Unused size of availability's storage in bytes as decimal string
|
||||
*/
|
||||
freeSize: string
|
||||
}
|
||||
/**
|
||||
* Unused size of availability's storage in bytes as decimal string
|
||||
*/
|
||||
freeSize: string;
|
||||
};
|
||||
|
||||
export const CodexCreateAvailabilityInput = v.strictObject({
|
||||
totalSize: v.pipe(v.number(), v.minValue(1)),
|
||||
duration: v.pipe(v.number(), v.minValue(1)),
|
||||
minPrice: v.number(),
|
||||
maxCollateral: v.number(),
|
||||
})
|
||||
totalSize: v.pipe(v.number(), v.minValue(1)),
|
||||
duration: v.pipe(v.number(), v.minValue(1)),
|
||||
minPrice: v.number(),
|
||||
maxCollateral: v.number(),
|
||||
});
|
||||
|
||||
export type CodexCreateAvailabilityInput = v.InferOutput<typeof CodexCreateAvailabilityInput>;
|
||||
export type CodexCreateAvailabilityInput = v.InferOutput<
|
||||
typeof CodexCreateAvailabilityInput
|
||||
>;
|
||||
|
||||
export const CodexUpdateAvailabilityInput = v.strictObject({
|
||||
id: v.string(),
|
||||
totalSize: v.optional(v.pipe(v.number(), v.minValue(1))),
|
||||
duration: v.optional(v.pipe(v.number(), v.minValue(1))),
|
||||
minPrice: v.optional(v.number()),
|
||||
maxCollateral: v.optional(v.number()),
|
||||
})
|
||||
id: v.string(),
|
||||
totalSize: v.optional(v.pipe(v.number(), v.minValue(1))),
|
||||
duration: v.optional(v.pipe(v.number(), v.minValue(1))),
|
||||
minPrice: v.optional(v.number()),
|
||||
maxCollateral: v.optional(v.number()),
|
||||
});
|
||||
|
||||
export type CodexUpdateAvailabilityInput = v.InferOutput<typeof CodexUpdateAvailabilityInput>;
|
||||
export type CodexUpdateAvailabilityInput = v.InferOutput<
|
||||
typeof CodexUpdateAvailabilityInput
|
||||
>;
|
||||
|
||||
export type CodexReservation = {
|
||||
id: string
|
||||
availabilityId: string
|
||||
requestId: string
|
||||
id: string;
|
||||
availabilityId: string;
|
||||
requestId: string;
|
||||
|
||||
/**
|
||||
* Size in bytes
|
||||
*/
|
||||
size: string
|
||||
/**
|
||||
* Size in bytes
|
||||
*/
|
||||
size: string;
|
||||
|
||||
/**
|
||||
* Slot Index as hexadecimal string
|
||||
*/
|
||||
slotIndex: string
|
||||
}
|
||||
/**
|
||||
* Slot Index as hexadecimal string
|
||||
*/
|
||||
slotIndex: string;
|
||||
};
|
||||
|
||||
export type CodexPurchase = {
|
||||
/**
|
||||
* Description of the request's state
|
||||
*/
|
||||
state: string
|
||||
/**
|
||||
* Description of the request's state
|
||||
*/
|
||||
state: string;
|
||||
|
||||
/**
|
||||
* If request failed, then here is presented the error message
|
||||
*/
|
||||
error: string
|
||||
/**
|
||||
* If request failed, then here is presented the error message
|
||||
*/
|
||||
error: string;
|
||||
|
||||
request: CodexStorageRequest
|
||||
}
|
||||
request: CodexStorageRequest;
|
||||
};
|
||||
|
||||
export const CodexCreateStorageRequestInput = v.strictObject({
|
||||
cid: v.string(),
|
||||
duration: v.pipe(v.number(), v.minValue(1)),
|
||||
reward: v.number(),
|
||||
proofProbability: v.number(),
|
||||
nodes: v.optional(v.number(), 1),
|
||||
tolerance: v.optional(v.number(), 0),
|
||||
expiry: v.pipe(v.number(), v.minValue(1)),
|
||||
collateral: v.number(),
|
||||
})
|
||||
cid: v.string(),
|
||||
duration: v.pipe(v.number(), v.minValue(1)),
|
||||
reward: v.number(),
|
||||
proofProbability: v.number(),
|
||||
nodes: v.optional(v.number(), 1),
|
||||
tolerance: v.optional(v.number(), 0),
|
||||
expiry: v.pipe(v.number(), v.minValue(1)),
|
||||
collateral: v.number(),
|
||||
});
|
||||
|
||||
export type CodexCreateStorageRequestInput = v.InferOutput<typeof CodexCreateStorageRequestInput>;
|
||||
export type CodexCreateStorageRequestInput = v.InferOutput<
|
||||
typeof CodexCreateStorageRequestInput
|
||||
>;
|
||||
|
||||
export type CodexCreateStorageRequestResponse = Omit<CodexCreateStorageRequestInput, "cid">
|
||||
export type CodexCreateStorageRequestResponse = Omit<
|
||||
CodexCreateStorageRequestInput,
|
||||
"cid"
|
||||
>;
|
||||
|
||||
@ -6,5 +6,6 @@ import { type CodexError } from "../errors/errors";
|
||||
* If the value represents an error, `error` is true and `data` will contain the error.
|
||||
* If the value is not an error, `error` is false and `data` will contain the requested data.
|
||||
*/
|
||||
export type SafeValue<T> = { error: false, data: T } | { error: true, data: CodexError }
|
||||
|
||||
export type SafeValue<T> =
|
||||
| { error: false; data: T }
|
||||
| { error: true; data: CodexError };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user