@xyo-network/api-call-witness 2.79.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +13 -0
  3. package/dist/browser/Payload.d.cts +31 -0
  4. package/dist/browser/Payload.d.cts.map +1 -0
  5. package/dist/browser/Payload.d.mts +31 -0
  6. package/dist/browser/Payload.d.mts.map +1 -0
  7. package/dist/browser/Payload.d.ts +31 -0
  8. package/dist/browser/Payload.d.ts.map +1 -0
  9. package/dist/browser/Witness.d.cts +21 -0
  10. package/dist/browser/Witness.d.cts.map +1 -0
  11. package/dist/browser/Witness.d.mts +21 -0
  12. package/dist/browser/Witness.d.mts.map +1 -0
  13. package/dist/browser/Witness.d.ts +21 -0
  14. package/dist/browser/Witness.d.ts.map +1 -0
  15. package/dist/browser/index.cjs +160 -0
  16. package/dist/browser/index.cjs.map +1 -0
  17. package/dist/browser/index.d.cts +3 -0
  18. package/dist/browser/index.d.cts.map +1 -0
  19. package/dist/browser/index.d.mts +3 -0
  20. package/dist/browser/index.d.mts.map +1 -0
  21. package/dist/browser/index.d.ts +3 -0
  22. package/dist/browser/index.d.ts.map +1 -0
  23. package/dist/browser/index.js +137 -0
  24. package/dist/browser/index.js.map +1 -0
  25. package/dist/browser/lib/checkIpfsUrl.d.cts +8 -0
  26. package/dist/browser/lib/checkIpfsUrl.d.cts.map +1 -0
  27. package/dist/browser/lib/checkIpfsUrl.d.mts +8 -0
  28. package/dist/browser/lib/checkIpfsUrl.d.mts.map +1 -0
  29. package/dist/browser/lib/checkIpfsUrl.d.ts +8 -0
  30. package/dist/browser/lib/checkIpfsUrl.d.ts.map +1 -0
  31. package/dist/browser/lib/index.d.cts +2 -0
  32. package/dist/browser/lib/index.d.cts.map +1 -0
  33. package/dist/browser/lib/index.d.mts +2 -0
  34. package/dist/browser/lib/index.d.mts.map +1 -0
  35. package/dist/browser/lib/index.d.ts +2 -0
  36. package/dist/browser/lib/index.d.ts.map +1 -0
  37. package/dist/node/Payload.d.cts +31 -0
  38. package/dist/node/Payload.d.cts.map +1 -0
  39. package/dist/node/Payload.d.mts +31 -0
  40. package/dist/node/Payload.d.mts.map +1 -0
  41. package/dist/node/Payload.d.ts +31 -0
  42. package/dist/node/Payload.d.ts.map +1 -0
  43. package/dist/node/Witness.d.cts +21 -0
  44. package/dist/node/Witness.d.cts.map +1 -0
  45. package/dist/node/Witness.d.mts +21 -0
  46. package/dist/node/Witness.d.mts.map +1 -0
  47. package/dist/node/Witness.d.ts +21 -0
  48. package/dist/node/Witness.d.ts.map +1 -0
  49. package/dist/node/index.cjs +168 -0
  50. package/dist/node/index.cjs.map +1 -0
  51. package/dist/node/index.d.cts +3 -0
  52. package/dist/node/index.d.cts.map +1 -0
  53. package/dist/node/index.d.mts +3 -0
  54. package/dist/node/index.d.mts.map +1 -0
  55. package/dist/node/index.d.ts +3 -0
  56. package/dist/node/index.d.ts.map +1 -0
  57. package/dist/node/index.js +138 -0
  58. package/dist/node/index.js.map +1 -0
  59. package/dist/node/lib/checkIpfsUrl.d.cts +8 -0
  60. package/dist/node/lib/checkIpfsUrl.d.cts.map +1 -0
  61. package/dist/node/lib/checkIpfsUrl.d.mts +8 -0
  62. package/dist/node/lib/checkIpfsUrl.d.mts.map +1 -0
  63. package/dist/node/lib/checkIpfsUrl.d.ts +8 -0
  64. package/dist/node/lib/checkIpfsUrl.d.ts.map +1 -0
  65. package/dist/node/lib/index.d.cts +2 -0
  66. package/dist/node/lib/index.d.cts.map +1 -0
  67. package/dist/node/lib/index.d.mts +2 -0
  68. package/dist/node/lib/index.d.mts.map +1 -0
  69. package/dist/node/lib/index.d.ts +2 -0
  70. package/dist/node/lib/index.d.ts.map +1 -0
  71. package/package.json +72 -0
  72. package/src/Payload.ts +51 -0
  73. package/src/Witness.ts +129 -0
  74. package/src/index.ts +2 -0
  75. package/src/lib/checkIpfsUrl.ts +31 -0
  76. package/src/lib/index.ts +1 -0
  77. package/typedoc.json +5 -0
@@ -0,0 +1,138 @@
1
+ // src/Payload.ts
2
+ var ApiCallSchema = "network.xyo.api.call";
3
+ var ApiCallResultSchema = "network.xyo.api.call.result";
4
+
5
+ // src/Witness.ts
6
+ import { assertEx as assertEx2 } from "@xylabs/assert";
7
+ import { Axios, AxiosJson } from "@xylabs/axios";
8
+ import { Buffer } from "@xylabs/buffer";
9
+ import { AbstractWitness } from "@xyo-network/abstract-witness";
10
+ import { PayloadHasher } from "@xyo-network/hash";
11
+ import { isPayloadOfSchemaType } from "@xyo-network/payload-model";
12
+ import { fromByteArray } from "base64-js";
13
+
14
+ // src/lib/checkIpfsUrl.ts
15
+ import { assertEx } from "@xylabs/assert";
16
+ var checkIpfsUrl = (urlToCheck, ipfsGateway) => {
17
+ try {
18
+ const url = new URL(urlToCheck);
19
+ let protocol = url.protocol;
20
+ let host = url.host;
21
+ let path = url.pathname;
22
+ const query = url.search;
23
+ if (protocol === "ipfs:") {
24
+ protocol = "https:";
25
+ host = assertEx(ipfsGateway, "No ipfsGateway provided");
26
+ path = url.host === "ipfs" ? `ipfs${path}` : `ipfs/${url.host}${path}`;
27
+ const root = `${protocol}//${host}/${path}`;
28
+ return (query == null ? void 0 : query.length) > 0 ? `${root}?${query}` : root;
29
+ } else {
30
+ return urlToCheck;
31
+ }
32
+ } catch (ex) {
33
+ const error = ex;
34
+ console.error(`${error.name}:${error.message} [${urlToCheck}]`);
35
+ console.log(error.stack);
36
+ return void 0;
37
+ }
38
+ };
39
+
40
+ // src/Witness.ts
41
+ var ApiCallWitnessConfigSchema = "network.xyo.api.call.witness.config";
42
+ var ApiCallWitness = class extends AbstractWitness {
43
+ static configSchemas = [ApiCallWitnessConfigSchema];
44
+ get accept() {
45
+ return this.config.accept;
46
+ }
47
+ get ipfsGateway() {
48
+ return this.params.ipfsGateway;
49
+ }
50
+ async observeHandler(inPayloads = []) {
51
+ await this.started("throw");
52
+ try {
53
+ const observations = await Promise.all(
54
+ inPayloads.filter(isPayloadOfSchemaType(ApiCallSchema)).map(async (call) => {
55
+ const { uri, verb } = call;
56
+ const validatedUri = assertEx2(checkIpfsUrl(uri, this.ipfsGateway), "Invalid URI");
57
+ if (verb === "get") {
58
+ return this.httpGet(validatedUri, uri);
59
+ }
60
+ const observation = {
61
+ call: await PayloadHasher.hashAsync(call),
62
+ schema: ApiCallResultSchema
63
+ };
64
+ return observation;
65
+ })
66
+ );
67
+ return observations;
68
+ } catch (ex) {
69
+ const error = ex;
70
+ console.log(`Error [${this.config.name}]: ${error.message}`);
71
+ throw error;
72
+ }
73
+ }
74
+ async httpGet(url, call) {
75
+ var _a, _b, _c;
76
+ const result = {
77
+ call,
78
+ schema: ApiCallResultSchema
79
+ };
80
+ try {
81
+ switch (this.accept) {
82
+ case "application/json": {
83
+ const axios = new AxiosJson();
84
+ const response = await axios.get(url);
85
+ if (response.status >= 200 && response.status < 300) {
86
+ const jsonResult = result;
87
+ jsonResult.data = response.data;
88
+ jsonResult.contentType = "application/json";
89
+ } else {
90
+ const errorResult = result;
91
+ errorResult.http = {
92
+ status: response.status
93
+ };
94
+ }
95
+ break;
96
+ }
97
+ default: {
98
+ const axios = new Axios({ responseType: "arraybuffer" });
99
+ const response = await axios.get(url);
100
+ if (response.status >= 200 && response.status < 300) {
101
+ const jsonResult = result;
102
+ jsonResult.data = fromByteArray(Buffer.from(response.data, "binary"));
103
+ jsonResult.contentType = ((_a = response.headers["content-type"]) == null ? void 0 : _a.toString()) ?? "application/octet-stream";
104
+ } else {
105
+ const errorResult = result;
106
+ errorResult.http = {
107
+ status: response.status
108
+ };
109
+ }
110
+ break;
111
+ }
112
+ }
113
+ } catch (ex) {
114
+ const axiosError = ex;
115
+ if (axiosError.isAxiosError) {
116
+ if (((_b = axiosError == null ? void 0 : axiosError.response) == null ? void 0 : _b.status) !== void 0) {
117
+ result.http = result.http ?? {};
118
+ result.http.status = (_c = axiosError == null ? void 0 : axiosError.response) == null ? void 0 : _c.status;
119
+ }
120
+ if ((axiosError == null ? void 0 : axiosError.code) !== void 0) {
121
+ result.http = result.http ?? {};
122
+ result.http.code = axiosError == null ? void 0 : axiosError.code;
123
+ }
124
+ return result;
125
+ } else {
126
+ throw ex;
127
+ }
128
+ }
129
+ return result;
130
+ }
131
+ };
132
+ export {
133
+ ApiCallResultSchema,
134
+ ApiCallSchema,
135
+ ApiCallWitness,
136
+ ApiCallWitnessConfigSchema
137
+ };
138
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Payload.ts","../../src/Witness.ts","../../src/lib/checkIpfsUrl.ts"],"sourcesContent":["import { Hash } from '@xyo-network/hash'\nimport { Payload } from '@xyo-network/payload-model'\n\nexport const ApiCallSchema = 'network.xyo.api.call'\nexport type ApiCallSchema = typeof ApiCallSchema\n\nexport type Verb = 'get' | 'post'\n\nexport type ApiCall = Payload<\n {\n uri: string\n verb?: Verb\n },\n ApiCallSchema\n>\n\nexport const ApiCallResultSchema = 'network.xyo.api.call.result'\nexport type ApiCallResultSchema = typeof ApiCallResultSchema\n\nexport interface HttpMeta {\n code?: string\n status?: number\n}\n\nexport type ApiCallJsonResult<T extends object | [] = object> = Payload<\n {\n call: Hash\n contentType: 'application/json'\n data: T\n },\n ApiCallResultSchema\n>\n\nexport type ApiCallBase64Result = Payload<\n {\n call: Hash\n contentType: Exclude<string, ApiCallJsonResult['contentType']>\n data: string\n },\n ApiCallResultSchema\n>\n\nexport type ApiCallErrorResult = Payload<\n {\n call: Hash\n http?: HttpMeta\n },\n ApiCallResultSchema\n>\n\nexport type ApiCallResult = ApiCallBase64Result | ApiCallJsonResult | ApiCallErrorResult\n","import { assertEx } from '@xylabs/assert'\nimport { Axios, AxiosError, AxiosJson } from '@xylabs/axios'\nimport { Buffer } from '@xylabs/buffer'\nimport { AbstractWitness } from '@xyo-network/abstract-witness'\nimport { Hash, PayloadHasher } from '@xyo-network/hash'\nimport { JsonArray, JsonObject } from '@xyo-network/object'\nimport { isPayloadOfSchemaType } from '@xyo-network/payload-model'\nimport { WitnessConfig, WitnessParams } from '@xyo-network/witness-model'\nimport { fromByteArray } from 'base64-js'\n\nimport { checkIpfsUrl } from './lib'\nimport {\n ApiCall,\n ApiCallBase64Result,\n ApiCallErrorResult,\n ApiCallJsonResult,\n ApiCallResult,\n ApiCallResultSchema,\n ApiCallSchema,\n Verb,\n} from './Payload'\n\nexport const ApiCallWitnessConfigSchema = 'network.xyo.api.call.witness.config'\nexport type ApiCallWitnessConfigSchema = typeof ApiCallWitnessConfigSchema\n\nexport type ApiCallWitnessConfig = WitnessConfig<{\n accept: 'application/json'\n schema: ApiCallWitnessConfigSchema\n verb?: Verb\n}>\n\nexport type ApiCallWitnessParams = WitnessParams<ApiCallWitnessConfig, { ipfsGateway?: string }>\n\nexport class ApiCallWitness<TParams extends ApiCallWitnessParams = ApiCallWitnessParams> extends AbstractWitness<TParams, ApiCall, ApiCallResult> {\n static override configSchemas = [ApiCallWitnessConfigSchema]\n\n get accept() {\n return this.config.accept\n }\n\n get ipfsGateway() {\n return this.params.ipfsGateway\n }\n\n protected override async observeHandler(inPayloads: ApiCall[] = []): Promise<ApiCallResult[]> {\n await this.started('throw')\n try {\n const observations = await Promise.all(\n inPayloads.filter(isPayloadOfSchemaType(ApiCallSchema)).map(async (call) => {\n const { uri, verb } = call\n\n const validatedUri = assertEx(checkIpfsUrl(uri, this.ipfsGateway), 'Invalid URI')\n\n if (verb === 'get') {\n return this.httpGet(validatedUri, uri)\n }\n\n const observation: ApiCallResult = {\n call: await PayloadHasher.hashAsync(call),\n schema: ApiCallResultSchema,\n }\n return observation\n }),\n )\n return observations\n } catch (ex) {\n const error = ex as Error\n console.log(`Error [${this.config.name}]: ${error.message}`)\n throw error\n }\n }\n\n private async httpGet(url: string, call: Hash): Promise<ApiCallResult> {\n const result: ApiCallResult = {\n call,\n schema: ApiCallResultSchema,\n }\n try {\n switch (this.accept) {\n case 'application/json': {\n const axios = new AxiosJson()\n const response = await axios.get<JsonArray | JsonObject>(url)\n if (response.status >= 200 && response.status < 300) {\n const jsonResult = result as ApiCallJsonResult\n jsonResult.data = response.data\n jsonResult.contentType = 'application/json'\n } else {\n const errorResult = result as ApiCallErrorResult\n errorResult.http = {\n status: response.status,\n }\n }\n break\n }\n default: {\n const axios = new Axios({ responseType: 'arraybuffer' })\n const response = await axios.get(url)\n if (response.status >= 200 && response.status < 300) {\n const jsonResult = result as ApiCallBase64Result\n jsonResult.data = fromByteArray(Buffer.from(response.data, 'binary'))\n jsonResult.contentType = response.headers['content-type']?.toString() ?? 'application/octet-stream'\n } else {\n const errorResult = result as ApiCallErrorResult\n errorResult.http = {\n status: response.status,\n }\n }\n break\n }\n }\n } catch (ex) {\n const axiosError = ex as AxiosError\n if (axiosError.isAxiosError) {\n if (axiosError?.response?.status !== undefined) {\n result.http = result.http ?? {}\n result.http.status = axiosError?.response?.status\n }\n if (axiosError?.code !== undefined) {\n result.http = result.http ?? {}\n result.http.code = axiosError?.code\n }\n return result\n } else {\n throw ex\n }\n }\n return result\n }\n}\n","import { assertEx } from '@xylabs/assert'\n\n/**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\nexport const checkIpfsUrl = (urlToCheck: string, ipfsGateway?: string) => {\n try {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = assertEx(ipfsGateway, 'No ipfsGateway provided')\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n } catch (ex) {\n const error = ex as Error\n console.error(`${error.name}:${error.message} [${urlToCheck}]`)\n console.log(error.stack)\n return undefined\n }\n}\n"],"mappings":"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","names":["assertEx","assertEx"]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Returns the equivalent IPFS gateway URL for the supplied URL.
3
+ * @param urlToCheck The URL to check
4
+ * @returns If the supplied URL is an IPFS URL, it converts the URL to the
5
+ * equivalent IPFS gateway URL. Otherwise, returns the original URL.
6
+ */
7
+ export declare const checkIpfsUrl: (urlToCheck: string, ipfsGateway?: string) => string | undefined;
8
+ //# sourceMappingURL=checkIpfsUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkIpfsUrl.d.ts","sourceRoot":"","sources":["../../../src/lib/checkIpfsUrl.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,eAAgB,MAAM,gBAAgB,MAAM,uBAsBpE,CAAA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Returns the equivalent IPFS gateway URL for the supplied URL.
3
+ * @param urlToCheck The URL to check
4
+ * @returns If the supplied URL is an IPFS URL, it converts the URL to the
5
+ * equivalent IPFS gateway URL. Otherwise, returns the original URL.
6
+ */
7
+ export declare const checkIpfsUrl: (urlToCheck: string, ipfsGateway?: string) => string | undefined;
8
+ //# sourceMappingURL=checkIpfsUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkIpfsUrl.d.ts","sourceRoot":"","sources":["../../../src/lib/checkIpfsUrl.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,eAAgB,MAAM,gBAAgB,MAAM,uBAsBpE,CAAA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Returns the equivalent IPFS gateway URL for the supplied URL.
3
+ * @param urlToCheck The URL to check
4
+ * @returns If the supplied URL is an IPFS URL, it converts the URL to the
5
+ * equivalent IPFS gateway URL. Otherwise, returns the original URL.
6
+ */
7
+ export declare const checkIpfsUrl: (urlToCheck: string, ipfsGateway?: string) => string | undefined;
8
+ //# sourceMappingURL=checkIpfsUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkIpfsUrl.d.ts","sourceRoot":"","sources":["../../../src/lib/checkIpfsUrl.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,eAAgB,MAAM,gBAAgB,MAAM,uBAsBpE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './checkIpfsUrl';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './checkIpfsUrl';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './checkIpfsUrl';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@xyo-network/api-call-witness",
3
+ "author": {
4
+ "email": "support@xyo.network",
5
+ "name": "XYO Development Team",
6
+ "url": "https://xyo.network"
7
+ },
8
+ "bugs": {
9
+ "email": "support@xyo.network",
10
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
11
+ },
12
+ "dependencies": {
13
+ "@xylabs/assert": "^2.13.8",
14
+ "@xylabs/axios": "^2.13.8",
15
+ "@xylabs/buffer": "^2.13.8",
16
+ "@xyo-network/abstract-witness": "~2.79.5",
17
+ "@xyo-network/hash": "~2.79.5",
18
+ "@xyo-network/object": "~2.79.5",
19
+ "@xyo-network/payload-model": "~2.79.5",
20
+ "@xyo-network/witness-model": "~2.79.5",
21
+ "base64-js": "^1.5.1"
22
+ },
23
+ "devDependencies": {
24
+ "@xylabs/jest-helpers": "^2.13.8",
25
+ "@xylabs/ts-scripts-yarn3": "^3.1.21",
26
+ "@xylabs/tsconfig": "^3.1.21",
27
+ "ethers": "^5.7.2",
28
+ "jest": "^29.7.0",
29
+ "typescript": "^5.2.2"
30
+ },
31
+ "description": "Primary SDK for using XYO Protocol 2.0",
32
+ "exports": {
33
+ ".": {
34
+ "browser": {
35
+ "require": {
36
+ "types": "./dist/browser/index.d.cts",
37
+ "default": "./dist/browser/index.cjs"
38
+ },
39
+ "import": {
40
+ "types": "./dist/browser/index.d.mts",
41
+ "default": "./dist/browser/index.js"
42
+ }
43
+ },
44
+ "node": {
45
+ "require": {
46
+ "types": "./dist/node/index.d.cts",
47
+ "default": "./dist/node/index.cjs"
48
+ },
49
+ "import": {
50
+ "types": "./dist/node/index.d.mts",
51
+ "default": "./dist/node/index.js"
52
+ }
53
+ }
54
+ },
55
+ "./package.json": "./package.json"
56
+ },
57
+ "main": "dist/node/index.cjs",
58
+ "module": "dist/node/index.js",
59
+ "types": "dist/node/index.d.mts",
60
+ "homepage": "https://xyo.network",
61
+ "license": "LGPL-3.0-only",
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
68
+ },
69
+ "sideEffects": false,
70
+ "version": "2.79.5",
71
+ "type": "module"
72
+ }
package/src/Payload.ts ADDED
@@ -0,0 +1,51 @@
1
+ import { Hash } from '@xyo-network/hash'
2
+ import { Payload } from '@xyo-network/payload-model'
3
+
4
+ export const ApiCallSchema = 'network.xyo.api.call'
5
+ export type ApiCallSchema = typeof ApiCallSchema
6
+
7
+ export type Verb = 'get' | 'post'
8
+
9
+ export type ApiCall = Payload<
10
+ {
11
+ uri: string
12
+ verb?: Verb
13
+ },
14
+ ApiCallSchema
15
+ >
16
+
17
+ export const ApiCallResultSchema = 'network.xyo.api.call.result'
18
+ export type ApiCallResultSchema = typeof ApiCallResultSchema
19
+
20
+ export interface HttpMeta {
21
+ code?: string
22
+ status?: number
23
+ }
24
+
25
+ export type ApiCallJsonResult<T extends object | [] = object> = Payload<
26
+ {
27
+ call: Hash
28
+ contentType: 'application/json'
29
+ data: T
30
+ },
31
+ ApiCallResultSchema
32
+ >
33
+
34
+ export type ApiCallBase64Result = Payload<
35
+ {
36
+ call: Hash
37
+ contentType: Exclude<string, ApiCallJsonResult['contentType']>
38
+ data: string
39
+ },
40
+ ApiCallResultSchema
41
+ >
42
+
43
+ export type ApiCallErrorResult = Payload<
44
+ {
45
+ call: Hash
46
+ http?: HttpMeta
47
+ },
48
+ ApiCallResultSchema
49
+ >
50
+
51
+ export type ApiCallResult = ApiCallBase64Result | ApiCallJsonResult | ApiCallErrorResult
package/src/Witness.ts ADDED
@@ -0,0 +1,129 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { Axios, AxiosError, AxiosJson } from '@xylabs/axios'
3
+ import { Buffer } from '@xylabs/buffer'
4
+ import { AbstractWitness } from '@xyo-network/abstract-witness'
5
+ import { Hash, PayloadHasher } from '@xyo-network/hash'
6
+ import { JsonArray, JsonObject } from '@xyo-network/object'
7
+ import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
8
+ import { WitnessConfig, WitnessParams } from '@xyo-network/witness-model'
9
+ import { fromByteArray } from 'base64-js'
10
+
11
+ import { checkIpfsUrl } from './lib'
12
+ import {
13
+ ApiCall,
14
+ ApiCallBase64Result,
15
+ ApiCallErrorResult,
16
+ ApiCallJsonResult,
17
+ ApiCallResult,
18
+ ApiCallResultSchema,
19
+ ApiCallSchema,
20
+ Verb,
21
+ } from './Payload'
22
+
23
+ export const ApiCallWitnessConfigSchema = 'network.xyo.api.call.witness.config'
24
+ export type ApiCallWitnessConfigSchema = typeof ApiCallWitnessConfigSchema
25
+
26
+ export type ApiCallWitnessConfig = WitnessConfig<{
27
+ accept: 'application/json'
28
+ schema: ApiCallWitnessConfigSchema
29
+ verb?: Verb
30
+ }>
31
+
32
+ export type ApiCallWitnessParams = WitnessParams<ApiCallWitnessConfig, { ipfsGateway?: string }>
33
+
34
+ export class ApiCallWitness<TParams extends ApiCallWitnessParams = ApiCallWitnessParams> extends AbstractWitness<TParams, ApiCall, ApiCallResult> {
35
+ static override configSchemas = [ApiCallWitnessConfigSchema]
36
+
37
+ get accept() {
38
+ return this.config.accept
39
+ }
40
+
41
+ get ipfsGateway() {
42
+ return this.params.ipfsGateway
43
+ }
44
+
45
+ protected override async observeHandler(inPayloads: ApiCall[] = []): Promise<ApiCallResult[]> {
46
+ await this.started('throw')
47
+ try {
48
+ const observations = await Promise.all(
49
+ inPayloads.filter(isPayloadOfSchemaType(ApiCallSchema)).map(async (call) => {
50
+ const { uri, verb } = call
51
+
52
+ const validatedUri = assertEx(checkIpfsUrl(uri, this.ipfsGateway), 'Invalid URI')
53
+
54
+ if (verb === 'get') {
55
+ return this.httpGet(validatedUri, uri)
56
+ }
57
+
58
+ const observation: ApiCallResult = {
59
+ call: await PayloadHasher.hashAsync(call),
60
+ schema: ApiCallResultSchema,
61
+ }
62
+ return observation
63
+ }),
64
+ )
65
+ return observations
66
+ } catch (ex) {
67
+ const error = ex as Error
68
+ console.log(`Error [${this.config.name}]: ${error.message}`)
69
+ throw error
70
+ }
71
+ }
72
+
73
+ private async httpGet(url: string, call: Hash): Promise<ApiCallResult> {
74
+ const result: ApiCallResult = {
75
+ call,
76
+ schema: ApiCallResultSchema,
77
+ }
78
+ try {
79
+ switch (this.accept) {
80
+ case 'application/json': {
81
+ const axios = new AxiosJson()
82
+ const response = await axios.get<JsonArray | JsonObject>(url)
83
+ if (response.status >= 200 && response.status < 300) {
84
+ const jsonResult = result as ApiCallJsonResult
85
+ jsonResult.data = response.data
86
+ jsonResult.contentType = 'application/json'
87
+ } else {
88
+ const errorResult = result as ApiCallErrorResult
89
+ errorResult.http = {
90
+ status: response.status,
91
+ }
92
+ }
93
+ break
94
+ }
95
+ default: {
96
+ const axios = new Axios({ responseType: 'arraybuffer' })
97
+ const response = await axios.get(url)
98
+ if (response.status >= 200 && response.status < 300) {
99
+ const jsonResult = result as ApiCallBase64Result
100
+ jsonResult.data = fromByteArray(Buffer.from(response.data, 'binary'))
101
+ jsonResult.contentType = response.headers['content-type']?.toString() ?? 'application/octet-stream'
102
+ } else {
103
+ const errorResult = result as ApiCallErrorResult
104
+ errorResult.http = {
105
+ status: response.status,
106
+ }
107
+ }
108
+ break
109
+ }
110
+ }
111
+ } catch (ex) {
112
+ const axiosError = ex as AxiosError
113
+ if (axiosError.isAxiosError) {
114
+ if (axiosError?.response?.status !== undefined) {
115
+ result.http = result.http ?? {}
116
+ result.http.status = axiosError?.response?.status
117
+ }
118
+ if (axiosError?.code !== undefined) {
119
+ result.http = result.http ?? {}
120
+ result.http.code = axiosError?.code
121
+ }
122
+ return result
123
+ } else {
124
+ throw ex
125
+ }
126
+ }
127
+ return result
128
+ }
129
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './Payload'
2
+ export * from './Witness'
@@ -0,0 +1,31 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+
3
+ /**
4
+ * Returns the equivalent IPFS gateway URL for the supplied URL.
5
+ * @param urlToCheck The URL to check
6
+ * @returns If the supplied URL is an IPFS URL, it converts the URL to the
7
+ * equivalent IPFS gateway URL. Otherwise, returns the original URL.
8
+ */
9
+ export const checkIpfsUrl = (urlToCheck: string, ipfsGateway?: string) => {
10
+ try {
11
+ const url = new URL(urlToCheck)
12
+ let protocol = url.protocol
13
+ let host = url.host
14
+ let path = url.pathname
15
+ const query = url.search
16
+ if (protocol === 'ipfs:') {
17
+ protocol = 'https:'
18
+ host = assertEx(ipfsGateway, 'No ipfsGateway provided')
19
+ path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`
20
+ const root = `${protocol}//${host}/${path}`
21
+ return query?.length > 0 ? `${root}?${query}` : root
22
+ } else {
23
+ return urlToCheck
24
+ }
25
+ } catch (ex) {
26
+ const error = ex as Error
27
+ console.error(`${error.name}:${error.message} [${urlToCheck}]`)
28
+ console.log(error.stack)
29
+ return undefined
30
+ }
31
+ }
@@ -0,0 +1 @@
1
+ export * from './checkIpfsUrl'
package/typedoc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "entryPoints": ["./src/index.ts"],
4
+ "tsconfig": "./tsconfig.typedoc.json"
5
+ }