diff --git a/package.json b/package.json index 80caa21..f42e36e 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@graphql-codegen/client-preset": "^4.1.0", "@jest/globals": "^29.7.0", "@types/jest": "^29.5.7", + "@types/jsonwebtoken": "^9", "@types/node": "^20.5.9", "jest": "^29.7.0", "ts-jest": "^29.1.1", @@ -39,6 +40,7 @@ "dotenv": "^16.3.1", "graphql": "^16.8.0", "graphql-request": "^6.1.0", + "jsonwebtoken": "^9.0.2", "prisma": "^5.6.0", "sentry": "^0.1.2", "subscriptions-transport-ws": "^0.11.0", diff --git a/src/headless-graphql-client.ts b/src/headless-graphql-client.ts index e611fda..cb2db6c 100644 --- a/src/headless-graphql-client.ts +++ b/src/headless-graphql-client.ts @@ -1,3 +1,5 @@ +import jwt from "jsonwebtoken"; +import { getEnv } from "./env"; import { Address } from "@planetarium/account"; import { BencodexDictionary, @@ -63,8 +65,22 @@ export class HeadlessGraphQLClient implements IHeadlessGraphQLClient { this._endpoints = this._planet.rpcEndpoints["headless.gql"]; this._endpointsIterator = this._endpoints[Symbol.iterator](); const endpoint = this.getEndpoint(); + + const secretKey = getEnv("NC_JWT_SECRET_KEY"); + const iss = getEnv("NC_JWT_ISS"); + this._client = new Client({ url: endpoint, + fetchOptions: () => { + if (secretKey && iss) { + return { + headers: { + Authorization: `Bearer ${this.generateJwtToken(secretKey, iss)}`, + }, + }; + } + return {}; + }, exchanges: [ retryExchange({ initialDelayMs: 1000, @@ -94,6 +110,16 @@ export class HeadlessGraphQLClient implements IHeadlessGraphQLClient { ); } + private generateJwtToken(secretKey: string, iss: string): string { + const payload = { + iss: iss, + iat: Math.floor(Date.now() / 1000), + exp: Math.floor(Date.now() / 1000) + 300, + }; + + return jwt.sign(payload, secretKey); + } + public getPlanetID(): string { return this._planet.id; } diff --git a/yarn.lock b/yarn.lock index 044464e..c76f193 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,6 +21,7 @@ __metadata: "@sentry/node": "npm:^7.76.0" "@slack/web-api": "npm:^6.10.0" "@types/jest": "npm:^29.5.7" + "@types/jsonwebtoken": "npm:^9" "@types/node": "npm:^20.5.9" "@urql/core": "npm:^4.2.0" "@urql/exchange-retry": "npm:^1.2.0" @@ -31,6 +32,7 @@ __metadata: graphql: "npm:^16.8.0" graphql-request: "npm:^6.1.0" jest: "npm:^29.7.0" + jsonwebtoken: "npm:^9.0.2" prisma: "npm:^5.6.0" sentry: "npm:^0.1.2" subscriptions-transport-ws: "npm:^0.11.0" @@ -3346,6 +3348,15 @@ __metadata: languageName: node linkType: hard +"@types/jsonwebtoken@npm:^9": + version: 9.0.7 + resolution: "@types/jsonwebtoken@npm:9.0.7" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/e1cd0e48fcae21b1d4378887a23453bd7212b480a131b11bcda2cdeb0687d03c9646ee5ba592e04cfaf76f7cc80f179950e627cdb3ebc90a5923bce49a35631a + languageName: node + linkType: hard + "@types/node@npm:*, @types/node@npm:>=12.0.0, @types/node@npm:^20.5.9": version: 20.9.1 resolution: "@types/node@npm:20.9.1" @@ -3887,6 +3898,13 @@ __metadata: languageName: node linkType: hard +"buffer-equal-constant-time@npm:1.0.1": + version: 1.0.1 + resolution: "buffer-equal-constant-time@npm:1.0.1" + checksum: 10c0/fb2294e64d23c573d0dd1f1e7a466c3e978fe94a4e0f8183937912ca374619773bef8e2aceb854129d2efecbbc515bbd0cc78d2734a3e3031edb0888531bbc8e + languageName: node + linkType: hard + "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" @@ -4477,6 +4495,15 @@ __metadata: languageName: node linkType: hard +"ecdsa-sig-formatter@npm:1.0.11": + version: 1.0.11 + resolution: "ecdsa-sig-formatter@npm:1.0.11" + dependencies: + safe-buffer: "npm:^5.0.1" + checksum: 10c0/ebfbf19d4b8be938f4dd4a83b8788385da353d63307ede301a9252f9f7f88672e76f2191618fd8edfc2f24679236064176fab0b78131b161ee73daa37125408c + languageName: node + linkType: hard + "electron-to-chromium@npm:^1.4.535": version: 1.4.587 resolution: "electron-to-chromium@npm:1.4.587" @@ -6201,6 +6228,45 @@ __metadata: languageName: node linkType: hard +"jsonwebtoken@npm:^9.0.2": + version: 9.0.2 + resolution: "jsonwebtoken@npm:9.0.2" + dependencies: + jws: "npm:^3.2.2" + lodash.includes: "npm:^4.3.0" + lodash.isboolean: "npm:^3.0.3" + lodash.isinteger: "npm:^4.0.4" + lodash.isnumber: "npm:^3.0.3" + lodash.isplainobject: "npm:^4.0.6" + lodash.isstring: "npm:^4.0.1" + lodash.once: "npm:^4.0.0" + ms: "npm:^2.1.1" + semver: "npm:^7.5.4" + checksum: 10c0/d287a29814895e866db2e5a0209ce730cbc158441a0e5a70d5e940eb0d28ab7498c6bf45029cc8b479639bca94056e9a7f254e2cdb92a2f5750c7f358657a131 + languageName: node + linkType: hard + +"jwa@npm:^1.4.1": + version: 1.4.1 + resolution: "jwa@npm:1.4.1" + dependencies: + buffer-equal-constant-time: "npm:1.0.1" + ecdsa-sig-formatter: "npm:1.0.11" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/5c533540bf38702e73cf14765805a94027c66a0aa8b16bc3e89d8d905e61a4ce2791e87e21be97d1293a5ee9d4f3e5e47737e671768265ca4f25706db551d5e9 + languageName: node + linkType: hard + +"jws@npm:^3.2.2": + version: 3.2.2 + resolution: "jws@npm:3.2.2" + dependencies: + jwa: "npm:^1.4.1" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/e770704533d92df358adad7d1261fdecad4d7b66fa153ba80d047e03ca0f1f73007ce5ed3fbc04d2eba09ba6e7e6e645f351e08e5ab51614df1b0aa4f384dfff + languageName: node + linkType: hard + "kleur@npm:^3.0.3": version: 3.0.3 resolution: "kleur@npm:3.0.3" @@ -6252,6 +6318,48 @@ __metadata: languageName: node linkType: hard +"lodash.includes@npm:^4.3.0": + version: 4.3.0 + resolution: "lodash.includes@npm:4.3.0" + checksum: 10c0/7ca498b9b75bf602d04e48c0adb842dfc7d90f77bcb2a91a2b2be34a723ad24bc1c8b3683ec6b2552a90f216c723cdea530ddb11a3320e08fa38265703978f4b + languageName: node + linkType: hard + +"lodash.isboolean@npm:^3.0.3": + version: 3.0.3 + resolution: "lodash.isboolean@npm:3.0.3" + checksum: 10c0/0aac604c1ef7e72f9a6b798e5b676606042401dd58e49f051df3cc1e3adb497b3d7695635a5cbec4ae5f66456b951fdabe7d6b387055f13267cde521f10ec7f7 + languageName: node + linkType: hard + +"lodash.isinteger@npm:^4.0.4": + version: 4.0.4 + resolution: "lodash.isinteger@npm:4.0.4" + checksum: 10c0/4c3e023a2373bf65bf366d3b8605b97ec830bca702a926939bcaa53f8e02789b6a176e7f166b082f9365bfec4121bfeb52e86e9040cb8d450e64c858583f61b7 + languageName: node + linkType: hard + +"lodash.isnumber@npm:^3.0.3": + version: 3.0.3 + resolution: "lodash.isnumber@npm:3.0.3" + checksum: 10c0/2d01530513a1ee4f72dd79528444db4e6360588adcb0e2ff663db2b3f642d4bb3d687051ae1115751ca9082db4fdef675160071226ca6bbf5f0c123dbf0aa12d + languageName: node + linkType: hard + +"lodash.isplainobject@npm:^4.0.6": + version: 4.0.6 + resolution: "lodash.isplainobject@npm:4.0.6" + checksum: 10c0/afd70b5c450d1e09f32a737bed06ff85b873ecd3d3d3400458725283e3f2e0bb6bf48e67dbe7a309eb371a822b16a26cca4a63c8c52db3fc7dc9d5f9dd324cbb + languageName: node + linkType: hard + +"lodash.isstring@npm:^4.0.1": + version: 4.0.1 + resolution: "lodash.isstring@npm:4.0.1" + checksum: 10c0/09eaf980a283f9eef58ef95b30ec7fee61df4d6bf4aba3b5f096869cc58f24c9da17900febc8ffd67819b4e29de29793190e88dc96983db92d84c95fa85d1c92 + languageName: node + linkType: hard + "lodash.memoize@npm:4.x": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" @@ -6259,6 +6367,13 @@ __metadata: languageName: node linkType: hard +"lodash.once@npm:^4.0.0": + version: 4.1.1 + resolution: "lodash.once@npm:4.1.1" + checksum: 10c0/46a9a0a66c45dd812fcc016e46605d85ad599fe87d71a02f6736220554b52ffbe82e79a483ad40f52a8a95755b0d1077fba259da8bfb6694a7abbf4a48f1fc04 + languageName: node + linkType: hard + "lodash.sortby@npm:^4.7.0": version: 4.7.0 resolution: "lodash.sortby@npm:4.7.0" @@ -6587,6 +6702,13 @@ __metadata: languageName: node linkType: hard +"ms@npm:^2.1.1": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + "mute-stream@npm:0.0.8": version: 0.0.8 resolution: "mute-stream@npm:0.0.8" @@ -7303,7 +7425,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": +"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3