diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..192b338 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + overrides: [ + { + env: { + node: true, + }, + files: [".eslintrc.{js,cjs}"], + parserOptions: { + sourceType: "script", + }, + }, + ], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + }, + plugins: ["@typescript-eslint"], + rules: {}, +}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6817b27..6421330 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,13 +5,12 @@ name: ci on: push: - branches: # only for pushes on master - - master - pull_request: # for all PRs regardless of its base branch + branches: # only for pushes on master + - master + pull_request: # for all PRs regardless of its base branch jobs: build-test: - runs-on: ubuntu-latest env: @@ -19,34 +18,34 @@ jobs: MNEMONIC: ${{ secrets.TEST_MNEMONIC }} steps: - - uses: actions/checkout@v2 - - - name: Use Node.js 14.x - uses: actions/setup-node@v1 - with: - node-version: 14.x - - - name: Install dependencies - run: yarn install - - - name: Build - run: yarn build - - - name: Run a panacea-core docker container - run: | - docker run --rm -d \ - -e CHAIN_ID="${CHAIN_ID}" \ - -e MNEMONIC="${MNEMONIC}" \ - -p 26657:26657 \ - -v $(pwd)/scripts:/root/scripts \ - --name core \ - ghcr.io/medibloc/panacea-core:master \ - bash /root/scripts/panacea-core/init.sh - - wget -qO- https://raw.githubusercontent.com/eficode/wait-for/v2.1.2/wait-for | sh -s -- localhost:26657 -t 30 - - - name: Run tests - env: - PANACEAD_ENABLED: true - TENDERMINT_URL: http://localhost:26657 - run: yarn test + - uses: actions/checkout@v2 + + - name: Use Node.js 14.x + uses: actions/setup-node@v1 + with: + node-version: 14.x + + - name: Install dependencies + run: yarn install + + - name: Build + run: yarn build + + - name: Run a panacea-core docker container + run: | + docker run --rm -d \ + -e CHAIN_ID="${CHAIN_ID}" \ + -e MNEMONIC="${MNEMONIC}" \ + -p 26657:26657 \ + -v $(pwd)/scripts:/root/scripts \ + --name core \ + ghcr.io/medibloc/panacea-core:master \ + bash /root/scripts/panacea-core/init.sh + + wget -qO- https://raw.githubusercontent.com/eficode/wait-for/v2.1.2/wait-for | sh -s -- localhost:26657 -t 30 + + - name: Run tests + env: + PANACEAD_ENABLED: true + TENDERMINT_URL: http://localhost:26657 + run: yarn test diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..31625e3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules + +build + +*.js + +src/proto +third_party \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0651f4e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,53 @@ +# Changelog + +## Unreleased + +TBD + +### Features + +- []() feat: + +## [v2.0.4](https://github.com/medibloc/panacea-js/releases/tag/v2.0.4) - 2023-07-05 + +### Features + +- [\#71](https://github.com/medibloc/panacea-js/pull/71) feat: export jwt in index.ts + +## [v2.0.3](https://github.com/medibloc/panacea-js/releases/tag/v2.0.3) - 2023-03-13 + +### Features + +- [\#68](https://github.com/medibloc/panacea-js/pull/68) feat: add DID Auth in JWT + +## [v2.0.2](https://github.com/medibloc/panacea-js/releases/tag/v2.0.2) - 2022-08-18 + +### Features + +- [\#64](https://github.com/medibloc/panacea-js/pull/64) feat: implement a function to convert a mnemonic to a secp256k1 private key + +## [v2.0.1](https://github.com/medibloc/panacea-js/releases/tag/v2.0.1) - 2022-06-03 + +### Features + +- [\#60](https://github.com/medibloc/panacea-js/pull/60) feat: add explicit `fee` parameters + +## [v2.0.0](https://github.com/medibloc/panacea-js/releases/tag/v2.0.0) - 2021-07-20 + +### Features + +- [\#37](https://github.com/medibloc/panacea-js/pull/37) feat: Support Panacea v2 based on Cosmos v0.42 Stargate + +## [v1.3.1](https://github.com/medibloc/panacea-js/releases/tag/v1.3.1) - 2020-11-25 + +### Bug fixes + +- [\#24](https://github.com/medibloc/panacea-js/pull/24) Follow up the new Cosmos REST spec for DID operations + +## [v1.3.0](https://github.com/medibloc/panacea-js/releases/tag/v1.3.0) - 2020-10-30 + +### Features + +- [\#5](https://github.com/medibloc/panacea-js/pull/5)~[\#18](https://github.com/medibloc/panacea-js/pull/18) Support DID operations +- [\#11](https://github.com/medibloc/panacea-js/pull/11), [\#19](https://github.com/medibloc/panacea-js/pull/19) Switch to Typescript +- [\#22](https://github.com/medibloc/panacea-js/pull/22) Follow up the new Cosmos v0.36.0+ REST spec diff --git a/jest.config.js b/jest.config.js index 7f7a575..f456d7f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,5 @@ // jest.config.js module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', + preset: "ts-jest", + testEnvironment: "node", }; diff --git a/package.json b/package.json index 7e8e2a9..a0b6fea 100644 --- a/package.json +++ b/package.json @@ -21,13 +21,17 @@ "proto-gen": "./protocgen.sh", "build": "tsc", "test": "jest", - "lint": "eslint src test --ext .ts,.tsx", - "prepublishOnly": "npm run build" + "lint": "eslint src --ext .ts", + "prettify": "prettier --write ." }, "devDependencies": { "@types/jest": "^29.5.12", "@types/node": "^20.11.27", + "@typescript-eslint/eslint-plugin": "^7.2.0", + "@typescript-eslint/parser": "^7.2.0", + "eslint": "^8.57.0", "jest": "^29.7.0", + "prettier": "^3.2.5", "ts-jest": "^29.1.2", "ts-proto": "^1.169.1", "typescript": "^5.4.2" diff --git a/src/__tests__/group-signing-panacea-client.spec.ts b/src/__tests__/group-signing-panacea-client.spec.ts index 805e2de..a57e9bc 100644 --- a/src/__tests__/group-signing-panacea-client.spec.ts +++ b/src/__tests__/group-signing-panacea-client.spec.ts @@ -1,12 +1,14 @@ -import {DirectSecp256k1HdWallet} from "@cosmjs/proto-signing"; -import {v4 as uuidv4} from "uuid"; -import {TextEncoder} from "util"; -import {Secp256k1HdWallet} from "@cosmjs/amino"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import { v4 as uuidv4 } from "uuid"; +import { TextEncoder } from "util"; +import { Secp256k1HdWallet } from "@cosmjs/amino"; import assert from "assert"; -import {panacead} from './utils/test-utils'; -import {panaceaWalletOpts, SigningPanaceaClient} from '../client/signing-panacea-client'; -import {GroupSigningPanaceaClient} from '../client/group-signing-panacea-client'; -import {MsgAddWriterRequest, MsgCreateTopicRequest} from '../proto/panacea/aol/v2/tx'; +import { panacead } from "./utils/test-utils"; +import { + panaceaWalletOpts, + SigningPanaceaClient, + GroupSigningPanaceaClient, +} from "../client"; jest.setTimeout(60000); @@ -16,22 +18,37 @@ describe("GroupSigningPanaceaClient", () => { let feePayerWallet: DirectSecp256k1HdWallet; beforeAll(async () => { - ownerWallet = await DirectSecp256k1HdWallet.fromMnemonic(panacead.mnemonic, panaceaWalletOpts); - writerWallet = await DirectSecp256k1HdWallet.generate(24, panaceaWalletOpts); - feePayerWallet = await DirectSecp256k1HdWallet.fromMnemonic(panacead.mnemonic, panaceaWalletOpts); + ownerWallet = await DirectSecp256k1HdWallet.fromMnemonic( + panacead.mnemonic, + panaceaWalletOpts, + ); + writerWallet = await DirectSecp256k1HdWallet.generate( + 24, + panaceaWalletOpts, + ); + feePayerWallet = await DirectSecp256k1HdWallet.fromMnemonic( + panacead.mnemonic, + panaceaWalletOpts, + ); }); describe("connectWithSigners", () => { it("works", async () => { - const client = await GroupSigningPanaceaClient.connectWithSigners(panacead.tendermintUrl, [feePayerWallet, writerWallet]); + const client = await GroupSigningPanaceaClient.connectWithSigners( + panacead.tendermintUrl, + [feePayerWallet, writerWallet], + ); expect(client).toBeTruthy(); client.disconnect(); }); it("doesn't work without signer", async () => { const fn = async () => { - await GroupSigningPanaceaClient.connectWithSigners(panacead.tendermintUrl, []); - } + await GroupSigningPanaceaClient.connectWithSigners( + panacead.tendermintUrl, + [], + ); + }; await expect(fn()).rejects.toThrow(Error); }); @@ -39,8 +56,11 @@ describe("GroupSigningPanaceaClient", () => { it("doesn't work with OfflineAminoSigner", async () => { const wallet = await Secp256k1HdWallet.generate(24, panaceaWalletOpts); const fn = async () => { - await GroupSigningPanaceaClient.connectWithSigners(panacead.tendermintUrl, [wallet]); - } + await GroupSigningPanaceaClient.connectWithSigners( + panacead.tendermintUrl, + [wallet], + ); + }; await expect(fn()).rejects.toThrow(Error); }); @@ -60,12 +80,20 @@ describe("GroupSigningPanaceaClient", () => { const [firstFeePayerAccount] = await feePayerWallet.getAccounts(); feePayerAddress = firstFeePayerAccount.address; - const client = await SigningPanaceaClient.connectWithSigner(panacead.tendermintUrl, ownerWallet); + const client = await SigningPanaceaClient.connectWithSigner( + panacead.tendermintUrl, + ownerWallet, + ); const amount = { denom: "umed", amount: "5000000", - } - const res = await client.sendTokens(ownerAddress, writerAddress, [amount], "auto") + }; + const res = await client.sendTokens( + ownerAddress, + writerAddress, + [amount], + "auto", + ); expect(res).toBeTruthy(); topicName = uuidv4(); @@ -73,8 +101,11 @@ describe("GroupSigningPanaceaClient", () => { describe("addRecord", () => { beforeAll(async () => { - const client = await SigningPanaceaClient.connectWithSigner(panacead.tendermintUrl, ownerWallet); - const fee = client.createFee(200000) + const client = await SigningPanaceaClient.connectWithSigner( + panacead.tendermintUrl, + ownerWallet, + ); + const fee = client.createFee(200000); const req = { topicName: topicName, @@ -95,16 +126,30 @@ describe("GroupSigningPanaceaClient", () => { }); it("works with a fee payer", async () => { - const client = await GroupSigningPanaceaClient.connectWithSigners(panacead.tendermintUrl, [feePayerWallet, writerWallet]); + const client = await GroupSigningPanaceaClient.connectWithSigners( + panacead.tendermintUrl, + [feePayerWallet, writerWallet], + ); const key = new TextEncoder().encode("key1"); const value = new TextEncoder().encode("value1"); const fee = client.createFee(200000); - const res = await client.addRecordWithFeePayer(ownerAddress, topicName, key, value, writerAddress, feePayerAddress, fee, ""); + const res = await client.addRecordWithFeePayer( + ownerAddress, + topicName, + key, + value, + writerAddress, + feePayerAddress, + fee, + "", + ); expect(res).toBeTruthy(); - const record = await client.getPanaceaClient().getRecord(ownerAddress, topicName, 0); + const record = await client + .getPanaceaClient() + .getRecord(ownerAddress, topicName, 0); assert(record); expect(record.writerAddress).toEqual(writerAddress); expect(record.key).toEqual(key); diff --git a/src/__tests__/panacea-client.test.ts b/src/__tests__/panacea-client.test.ts index f308607..8456dca 100644 --- a/src/__tests__/panacea-client.test.ts +++ b/src/__tests__/panacea-client.test.ts @@ -1,20 +1,23 @@ -import {PanaceaClient} from '../client/panacea-client'; -import {panacead} from './utils/test-utils'; -import {DirectSecp256k1HdWallet} from '@cosmjs/proto-signing'; -import {panaceaWalletOpts} from '../client/signing-panacea-client'; +import { PanaceaClient } from "../client/panacea-client"; +import { panacead } from "./utils/test-utils"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import { panaceaWalletOpts } from "../client/signing-panacea-client"; -describe('Panacea client', () => { - it('connect', async () => { +describe("Panacea client", () => { + it("connect", async () => { const client = await PanaceaClient.connect(panacead.tendermintUrl); expect(client).toBeTruthy(); }); - describe('AOL', () => { + describe("AOL", () => { let ownerAddress: string; let client: PanaceaClient; beforeAll(async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(panacead.mnemonic, panaceaWalletOpts); + const wallet = await DirectSecp256k1HdWallet.fromMnemonic( + panacead.mnemonic, + panaceaWalletOpts, + ); const [firstAddress] = await wallet.getAccounts(); ownerAddress = firstAddress.address; client = await PanaceaClient.connect(panacead.tendermintUrl); @@ -30,7 +33,5 @@ describe('Panacea client', () => { expect(topic).toBeUndefined(); }); }); - - }); -}); \ No newline at end of file +}); diff --git a/src/__tests__/secp256k1.spec.ts b/src/__tests__/secp256k1.spec.ts index d11c575..58fa8bf 100644 --- a/src/__tests__/secp256k1.spec.ts +++ b/src/__tests__/secp256k1.spec.ts @@ -1,21 +1,32 @@ -import { Secp256k1 as CryptoSecp256k1, stringToPath, sha256 } from "@cosmjs/crypto"; +import { + Secp256k1 as CryptoSecp256k1, + stringToPath, + sha256, +} from "@cosmjs/crypto"; import { TextEncoder } from "util"; -import * as jose from 'jose' -import {Secp256k1} from "../crypto"; -import {panacead} from "./utils/test-utils"; +import * as jose from "jose"; +import { Secp256k1 } from "../crypto"; +import { panacead } from "./utils/test-utils"; describe("Secp256k1", () => { - it("parseMnemonicToPrivateKey", async () => { const body = "testBody"; const hashedBody = sha256(new TextEncoder().encode(body)); const hdPath = stringToPath("m/44'/371'/0'/0/0"); - const privateKey = await Secp256k1.parseMnemonicToPrivateKey(panacead.mnemonic, hdPath); - const {pubkey} = await CryptoSecp256k1.makeKeypair(privateKey); + const privateKey = await Secp256k1.parseMnemonicToPrivateKey( + panacead.mnemonic, + hdPath, + ); + const { pubkey } = await CryptoSecp256k1.makeKeypair(privateKey); - const signature = await CryptoSecp256k1.createSignature(hashedBody, privateKey) - expect(CryptoSecp256k1.verifySignature(signature, hashedBody, pubkey)).toBeTruthy() + const signature = await CryptoSecp256k1.createSignature( + hashedBody, + privateKey, + ); + expect( + CryptoSecp256k1.verifySignature(signature, hashedBody, pubkey), + ).toBeTruthy(); }); it("uncompressPublicKey", async () => { @@ -24,8 +35,12 @@ describe("Secp256k1", () => { const pubKeyCompressed = Secp256k1.getPublicKeyCompressed(privKey); const pubKeyUncompressed = Secp256k1.getPublicKeyUncompressed(privKey); - expect(Secp256k1.uncompressPublicKey(pubKeyCompressed)).toEqual(pubKeyUncompressed); - expect(Secp256k1.uncompressPublicKey(pubKeyUncompressed)).toEqual(pubKeyUncompressed); + expect(Secp256k1.uncompressPublicKey(pubKeyCompressed)).toEqual( + pubKeyUncompressed, + ); + expect(Secp256k1.uncompressPublicKey(pubKeyUncompressed)).toEqual( + pubKeyUncompressed, + ); }); it("convertPrivateKeyToJWK", async () => { @@ -46,7 +61,9 @@ describe("Secp256k1", () => { it("convertPublicKeyToJWK", async () => { const privKey = Secp256k1.generatePrivateKey(); - const jwk = Secp256k1.convertPublicKeyToJWK(Secp256k1.getPublicKeyUncompressed(privKey)); + const jwk = Secp256k1.convertPublicKeyToJWK( + Secp256k1.getPublicKeyUncompressed(privKey), + ); expect(jwk.kty).toEqual("EC"); expect(jwk.crv).toEqual("secp256k1"); expect(jwk.d).toBeUndefined(); diff --git a/src/__tests__/signing-panacea-client.test.ts b/src/__tests__/signing-panacea-client.test.ts index 62d94df..e84721d 100644 --- a/src/__tests__/signing-panacea-client.test.ts +++ b/src/__tests__/signing-panacea-client.test.ts @@ -1,25 +1,31 @@ -import {DirectSecp256k1HdWallet} from '@cosmjs/proto-signing'; -import {panacead} from './utils/test-utils'; -import {panaceaWalletOpts, SigningPanaceaClient} from '../client/signing-panacea-client'; -import {v4} from 'uuid'; -import {PanaceaClient} from "../client/panacea-client"; -import {Secp256k1} from "../crypto"; -import {DIDDocument} from "../proto/panacea/did/v2/did"; -import {DidUtil} from "../did"; -import {isDeliverTxSuccess} from "@cosmjs/stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import { panacead } from "./utils/test-utils"; +import { + panaceaWalletOpts, + SigningPanaceaClient, +} from "../client/signing-panacea-client"; +import { v4 } from "uuid"; +import { PanaceaClient } from "../client/panacea-client"; +import { Secp256k1 } from "../crypto"; +import { DIDDocument } from "../proto/panacea/did/v2/did"; +import { DidUtil } from "../did"; +import { isDeliverTxSuccess } from "@cosmjs/stargate"; import assert from "assert"; -import {TxRaw} from 'cosmjs-types/cosmos/tx/v1beta1/tx'; +import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; jest.setTimeout(60000); -describe('', () => { +describe("", () => { let wallet: DirectSecp256k1HdWallet; beforeAll(async () => { - wallet = await DirectSecp256k1HdWallet.fromMnemonic(panacead.mnemonic, panaceaWalletOpts); + wallet = await DirectSecp256k1HdWallet.fromMnemonic( + panacead.mnemonic, + panaceaWalletOpts, + ); }); - describe('AOL', () => { + describe("AOL", () => { let ownerAddress: string; let topicName: string; let client: SigningPanaceaClient; @@ -29,36 +35,49 @@ describe('', () => { ownerAddress = firstAccount.address; topicName = v4(); - client = await SigningPanaceaClient.connectWithSigner(panacead.tendermintUrl, wallet); + client = await SigningPanaceaClient.connectWithSigner( + panacead.tendermintUrl, + wallet, + ); }); afterAll(() => { client.disconnect(); }); - it('All aol test', async () => { + it("All aol test", async () => { const createTopicReq = { ownerAddress: ownerAddress, topicName: topicName, - description: 'description!', + description: "description!", }; - const createTopicRes = await client.createTopic(createTopicReq, client.createFee(200000), 'memo!'); + const createTopicRes = await client.createTopic( + createTopicReq, + client.createFee(200000), + "memo!", + ); expect(createTopicRes).toBeTruthy(); - let topic = await client.getPanaceaClient().getTopic(ownerAddress, topicName); + let topic = await client + .getPanaceaClient() + .getTopic(ownerAddress, topicName); expect(topic).toBeTruthy(); expect(createTopicReq.description).toBe(topic?.description); expect(0).toBe(topic?.totalWriters.toNumber()); expect(0).toBe(topic?.totalRecords.toNumber()); - let addWriterReq = { + const addWriterReq = { ownerAddress: ownerAddress, writerAddress: ownerAddress, topicName: topicName, - moniker: 'moniker', - description: 'my description', + moniker: "moniker", + description: "my description", }; - const addWriterRes = await client.addWriter(addWriterReq, client.createFee(200000), 'memo!'); + const addWriterRes = await client.addWriter( + addWriterReq, + client.createFee(200000), + "memo!", + ); expect(addWriterRes).toBeTruthy(); topic = await client.getPanaceaClient().getTopic(ownerAddress, topicName); @@ -66,20 +85,26 @@ describe('', () => { expect(createTopicReq.description).toBe(topic?.description); expect(1).toBe(topic?.totalWriters.toNumber()); expect(0).toBe(topic?.totalRecords.toNumber()); - const writer = await client.getPanaceaClient().getWriter(ownerAddress, topicName, ownerAddress); + const writer = await client + .getPanaceaClient() + .getWriter(ownerAddress, topicName, ownerAddress); expect(addWriterReq.moniker).toBe(writer?.moniker); expect(addWriterReq.description).toBe(writer?.description); - const key = new TextEncoder().encode('key1'); - const value = new TextEncoder().encode('value1'); - const addRecordRes = await client.addRecord({ - key: key, - value: value, - topicName: topicName, - ownerAddress: ownerAddress, - writerAddress: ownerAddress, - feePayerAddress: '', - }, client.createFee(200000), 'memo!'); + const key = new TextEncoder().encode("key1"); + const value = new TextEncoder().encode("value1"); + const addRecordRes = await client.addRecord( + { + key: key, + value: value, + topicName: topicName, + ownerAddress: ownerAddress, + writerAddress: ownerAddress, + feePayerAddress: "", + }, + client.createFee(200000), + "memo!", + ); expect(addRecordRes).toBeTruthy(); topic = await client.getPanaceaClient().getTopic(ownerAddress, topicName); @@ -88,14 +113,16 @@ describe('', () => { expect(1).toBe(topic?.totalWriters.toNumber()); expect(1).toBe(topic?.totalRecords.toNumber()); - const record = await client.getPanaceaClient().getRecord(ownerAddress, topicName, 0); + const record = await client + .getPanaceaClient() + .getRecord(ownerAddress, topicName, 0); expect(record?.key.toString()).toBe(key.toString()); expect(record?.value.toString()).toBe(value.toString()); expect(record?.writerAddress).toBe(ownerAddress); }); }); - describe('DID', () => { + describe("DID", () => { let fromAddress: string; let client: SigningPanaceaClient; let queryClient: PanaceaClient; @@ -104,7 +131,10 @@ describe('', () => { beforeAll(async () => { const [firstAccount] = await wallet.getAccounts(); fromAddress = firstAccount.address; - client = await SigningPanaceaClient.connectWithSigner(panacead.tendermintUrl, wallet); + client = await SigningPanaceaClient.connectWithSigner( + panacead.tendermintUrl, + wallet, + ); queryClient = await PanaceaClient.connect(panacead.tendermintUrl); offlineClient = await SigningPanaceaClient.offline(wallet); }); @@ -113,23 +143,25 @@ describe('', () => { client.disconnect(); }); - it('All did test', async () => { + it("All did test", async () => { const privKey = Secp256k1.generatePrivateKey(); const didDocument = generateDidDocument(privKey); let signature = DidUtil.signDidDocument(privKey, didDocument); - let createDidReq = { + const createDidReq = { did: didDocument.id, document: didDocument, verificationMethodId: didDocument.verificationMethods[0].id, signature: signature, fromAddress: fromAddress, }; - let res = await client.createDid(createDidReq, 'auto'); - console.log('create', res); + let res = await client.createDid(createDidReq, "auto"); + console.log("create", res); expect(isDeliverTxSuccess(res)).toBeTruthy(); - let getDIDDocumentWithSeq = await client.getPanaceaClient().getDid(didDocument.id); + let getDIDDocumentWithSeq = await client + .getPanaceaClient() + .getDid(didDocument.id); assert(getDIDDocumentWithSeq); expect(getDIDDocumentWithSeq.document).toEqual(didDocument); @@ -137,7 +169,11 @@ describe('', () => { verificationMethodId: didDocument.verificationMethods[0].id, verificationMethod: undefined, }); - signature = DidUtil.signDidDocument(privKey, didDocument, getDIDDocumentWithSeq.sequence); + signature = DidUtil.signDidDocument( + privKey, + didDocument, + getDIDDocumentWithSeq.sequence, + ); const updateDidReq = { did: didDocument.id, @@ -145,59 +181,66 @@ describe('', () => { verificationMethodId: didDocument.verificationMethods[0].id, signature: signature, fromAddress: fromAddress, - } - res = await client.updateDid(updateDidReq, 'auto'); - console.log('update', res); + }; + res = await client.updateDid(updateDidReq, "auto"); + console.log("update", res); expect(isDeliverTxSuccess(res)).toBeTruthy(); - getDIDDocumentWithSeq = await client.getPanaceaClient().getDid(didDocument.id); + getDIDDocumentWithSeq = await client + .getPanaceaClient() + .getDid(didDocument.id); console.log(getDIDDocumentWithSeq?.document?.verificationMethods); console.log(getDIDDocumentWithSeq?.sequence.toNumber()); assert(getDIDDocumentWithSeq); expect(getDIDDocumentWithSeq.document).toEqual(didDocument); }); - it('create DID with offline signer', - async () => { - const privKey = Secp256k1.generatePrivateKey(); - const didDocument = generateDidDocument(privKey); - const signature = DidUtil.signDidDocument(privKey, didDocument); - const address = (await wallet.getAccounts())[0].address; - - const account = await queryClient.getAccount(address); - expect(account).toBeTruthy(); - - const createDidReq = { - did: didDocument.id, - document: didDocument, - verificationMethodId: didDocument.verificationMethods[0].id, - signature: signature, - fromAddress: fromAddress, - }; - - const msg = { - typeUrl: SigningPanaceaClient.msgTypeCreateDid, - value: createDidReq, - } - - const signerData = { - accountNumber: account!.accountNumber, - sequence: account!.sequence, - chainId: await queryClient.getChainId(), - }; - - const fee = offlineClient.createFee(200000); // 5umed * 200000 = 1000000umed(1MED) - const memo = 'This is memo.'; - - const txRaw = await offlineClient.sign(address, [msg], fee, memo, signerData); - const txBytes = TxRaw.encode(txRaw).finish(); - - const res = await client.broadcastTx(txBytes, 300, 8000); - expect(isDeliverTxSuccess(res)).toBeTruthy(); - }); - }) + it("create DID with offline signer", async () => { + const privKey = Secp256k1.generatePrivateKey(); + const didDocument = generateDidDocument(privKey); + const signature = DidUtil.signDidDocument(privKey, didDocument); + const address = (await wallet.getAccounts())[0].address; + + const account = await queryClient.getAccount(address); + expect(account).toBeTruthy(); + + const createDidReq = { + did: didDocument.id, + document: didDocument, + verificationMethodId: didDocument.verificationMethods[0].id, + signature: signature, + fromAddress: fromAddress, + }; - describe('Pnft', () => { + const msg = { + typeUrl: SigningPanaceaClient.msgTypeCreateDid, + value: createDidReq, + }; + + const signerData = { + accountNumber: account!.accountNumber, + sequence: account!.sequence, + chainId: await queryClient.getChainId(), + }; + + const fee = offlineClient.createFee(200000); // 5umed * 200000 = 1000000umed(1MED) + const memo = "This is memo."; + + const txRaw = await offlineClient.sign( + address, + [msg], + fee, + memo, + signerData, + ); + const txBytes = TxRaw.encode(txRaw).finish(); + + const res = await client.broadcastTx(txBytes, 300, 8000); + expect(isDeliverTxSuccess(res)).toBeTruthy(); + }); + }); + + describe("Pnft", () => { let fromAddress: string; let toAddress: string; let client: SigningPanaceaClient; @@ -205,24 +248,31 @@ describe('', () => { beforeAll(async () => { const [firstAccount] = await wallet.getAccounts(); fromAddress = firstAccount.address; - client = await SigningPanaceaClient.connectWithSigner(panacead.tendermintUrl, wallet); - toAddress = (await (await DirectSecp256k1HdWallet.generate(24, panaceaWalletOpts)).getAccounts())[0].address + client = await SigningPanaceaClient.connectWithSigner( + panacead.tendermintUrl, + wallet, + ); + toAddress = ( + await ( + await DirectSecp256k1HdWallet.generate(24, panaceaWalletOpts) + ).getAccounts() + )[0].address; }); afterEach(() => { client.disconnect(); }); - it('All pnft test', async () => { + it("All pnft test", async () => { const fee = client.createFee(200000); const denomId = v4(); const createDenomReq = { id: denomId, - name: 'medibloc test create denom', - symbol: 'medibloc', - description: 'medibloc denom description', - data: 'no data', + name: "medibloc test create denom", + symbol: "medibloc", + description: "medibloc denom description", + data: "no data", creator: fromAddress, }; let res = await client.createDenom(createDenomReq, fee); @@ -235,18 +285,18 @@ describe('', () => { expect(denom!.symbol).toBe(createDenomReq.symbol); expect(denom!.description).toBe(createDenomReq.description); expect(denom!.data).toBe(createDenomReq.data); - expect(denom!.uri).toBe(''); - expect(denom!.uriHash).toBe(''); + expect(denom!.uri).toBe(""); + expect(denom!.uriHash).toBe(""); expect(denom!.owner).toBe(fromAddress); const updateDenomReq = { id: denomId, - name: 'mediboc test update denom', - symbol: 'medibloc limited', - description: 'change denom test', - uri: 'medibloc uri', - uriHash: 'medibloc uri hash', - data: 'clean', + name: "mediboc test update denom", + symbol: "medibloc limited", + description: "change denom test", + uri: "medibloc uri", + uriHash: "medibloc uri hash", + data: "clean", updater: fromAddress, }; res = await client.updateDenom(updateDenomReq, fee); @@ -263,14 +313,13 @@ describe('', () => { expect(denom!.uriHash).toBe(updateDenomReq.uriHash); expect(denom!.owner).toBe(fromAddress); - const pnftId = v4(); const firstPnftReq = { denomId: denomId, id: pnftId, - name: 'medibloc test nft', - description: 'This is medibloc first nft', - data: 'no data', + name: "medibloc test nft", + description: "This is medibloc first nft", + data: "no data", creator: fromAddress, }; res = await client.mintPNFT(firstPnftReq, fee); @@ -283,8 +332,8 @@ describe('', () => { expect(pnft!.name).toBe(firstPnftReq.name); expect(pnft!.description).toBe(firstPnftReq.description); expect(pnft!.data).toBe(firstPnftReq.data); - expect(pnft!.uri).toBe(''); - expect(pnft!.uriHash).toBe(''); + expect(pnft!.uri).toBe(""); + expect(pnft!.uriHash).toBe(""); expect(pnft!.creator).toBe(fromAddress); expect(pnft!.owner).toBe(fromAddress); @@ -304,8 +353,8 @@ describe('', () => { expect(pnft!.name).toBe(firstPnftReq.name); expect(pnft!.description).toBe(firstPnftReq.description); expect(pnft!.data).toBe(firstPnftReq.data); - expect(pnft!.uri).toBe(''); - expect(pnft!.uriHash).toBe(''); + expect(pnft!.uri).toBe(""); + expect(pnft!.uriHash).toBe(""); expect(pnft!.creator).toBe(fromAddress); expect(pnft!.owner).toBe(toAddress); @@ -314,9 +363,9 @@ describe('', () => { const secondPNftReq = { denomId: denomId, id: v4(), - name: 'medibloc test nft', - description: 'This is medibloc first nft', - data: 'no data', + name: "medibloc test nft", + description: "This is medibloc first nft", + data: "no data", creator: fromAddress, }; res = await client.mintPNFT(secondPNftReq, fee); @@ -332,10 +381,9 @@ describe('', () => { expect(isDeliverTxSuccess(res)).toBeTruthy(); pnft = await client.getPanaceaClient().getPnft(denomId, secondPNftReq.id); - expect(pnft).toBeUndefined() + expect(pnft).toBeUndefined(); }); - - }) + }); }); // A test utility function @@ -346,14 +394,14 @@ function generateDidDocument(privKey: Uint8Array): DIDDocument { const verificationMethodId = `${did}#key1`; return { contexts: { - values: ['https://www.w3.org/ns/did/v1'], + values: ["https://www.w3.org/ns/did/v1"], }, id: did, controller: undefined, verificationMethods: [ { id: verificationMethodId, - type: 'EcdsaSecp256k1VerificationKey2019', + type: "EcdsaSecp256k1VerificationKey2019", controller: did, publicKeyBase58: DidUtil.getPublicKeyBase58(pubKeyCompressed), }, @@ -371,4 +419,3 @@ function generateDidDocument(privKey: Uint8Array): DIDDocument { services: [], }; } - diff --git a/src/__tests__/utils/test-utils.ts b/src/__tests__/utils/test-utils.ts index 761d69c..8afc5cf 100644 --- a/src/__tests__/utils/test-utils.ts +++ b/src/__tests__/utils/test-utils.ts @@ -1,5 +1,8 @@ export const panacead = { - tendermintUrl: process.env.TENDERMINT_URL || "https://testnet-rpc.gopanacea.org", + tendermintUrl: + process.env.TENDERMINT_URL || "https://testnet-rpc.gopanacea.org", chainId: process.env.CHAIN_ID || "hygieia-1", - mnemonic: process.env.MNEMONIC || "frame resist nice body can breeze silk casino old trap eager treat donor grab chronic silly palace repeat pole final strategy deny nasty stone", -} \ No newline at end of file + mnemonic: + process.env.MNEMONIC || + "frame resist nice body can breeze silk casino old trap eager treat donor grab chronic silly palace repeat pole final strategy deny nasty stone", +}; diff --git a/src/client/group-signing-panacea-client.ts b/src/client/group-signing-panacea-client.ts index 66c90bc..ab4c0e1 100644 --- a/src/client/group-signing-panacea-client.ts +++ b/src/client/group-signing-panacea-client.ts @@ -1,23 +1,28 @@ -import {SigningPanaceaClient} from './signing-panacea-client'; +import { SigningPanaceaClient } from "./signing-panacea-client"; import { AccountData, EncodeObject, encodePubkey, - isOfflineDirectSigner, makeSignDoc, + isOfflineDirectSigner, + makeSignDoc, OfflineSigner, TxBodyEncodeObject, -} from '@cosmjs/proto-signing'; -import {DeliverTxResponse, SignerData, SigningStargateClientOptions, StdFee} from '@cosmjs/stargate'; -import {Tendermint37Client} from '@cosmjs/tendermint-rpc/build/tendermint37'; -import {AuthInfo, SignerInfo, TxRaw} from 'cosmjs-types/cosmos/tx/v1beta1/tx'; -import {encodeSecp256k1Pubkey} from '@cosmjs/amino'; -import {Int53} from '@cosmjs/math'; -import assert from 'assert'; -import {fromBase64} from '@cosmjs/encoding'; -import {Any} from 'cosmjs-types/google/protobuf/any'; -import {Coin} from 'cosmjs-types/cosmos/base/v1beta1/coin'; -import {SignMode} from 'cosmjs-types/cosmos/tx/signing/v1beta1/signing'; -import Long from 'long'; +} from "@cosmjs/proto-signing"; +import { + DeliverTxResponse, + SignerData, + SigningStargateClientOptions, + StdFee, +} from "@cosmjs/stargate"; +import { Tendermint37Client } from "@cosmjs/tendermint-rpc/build/tendermint37"; +import { AuthInfo, SignerInfo, TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; +import { encodeSecp256k1Pubkey } from "@cosmjs/amino"; +import { Int53 } from "@cosmjs/math"; +import assert from "assert"; +import { fromBase64 } from "@cosmjs/encoding"; +import { Any } from "cosmjs-types/google/protobuf/any"; +import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin"; +import { SignMode } from "cosmjs-types/cosmos/tx/signing/v1beta1/signing"; /** * A class for executing transactions to Panacea with signing by multiple addresses (aka. Group Signing). @@ -26,7 +31,7 @@ import Long from 'long'; * This class extends SigningPanaceaClient, so that you can execute non-group-signing transactions as well. * Then, the first signer will be used for signing transactions. */ -export class GroupSigningPanaceaClient extends SigningPanaceaClient{ +export class GroupSigningPanaceaClient extends SigningPanaceaClient { private readonly signers: OfflineSigner[]; /** @@ -58,7 +63,9 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ } signers.forEach((signer) => { if (!isOfflineDirectSigner(signer)) { - throw new Error("signer must be OfflineDirectSigner. OfflineAminoSigner is not supported."); + throw new Error( + "signer must be OfflineDirectSigner. OfflineAminoSigner is not supported.", + ); } }); this.signers = signers; @@ -70,7 +77,16 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ * * Make sure that GroupSigningPanaceaClient was created with [feePayerSigner, writerSigner]. The order matters. */ - async addRecordWithFeePayer(ownerAddress: string, topicName: string, key: Uint8Array, value: Uint8Array, writerAddress: string, feePayerAddress: string, fee: StdFee, memo?: string): Promise { + async addRecordWithFeePayer( + ownerAddress: string, + topicName: string, + key: Uint8Array, + value: Uint8Array, + writerAddress: string, + feePayerAddress: string, + fee: StdFee, + memo?: string, + ): Promise { const msg = { typeUrl: GroupSigningPanaceaClient.msgTypeAddRecord, value: { @@ -80,9 +96,14 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ writerAddress: writerAddress, ownerAddress: ownerAddress, feePayerAddress: feePayerAddress, - } - } - return this.groupSignAndBroadcast([feePayerAddress, writerAddress], [msg], fee, memo); + }, + }; + return this.groupSignAndBroadcast( + [feePayerAddress, writerAddress], + [msg], + fee, + memo, + ); } // Reference: https://github.com/cosmos/cosmjs/blob/06fbc34f72f12c30a396c3ca296f80eca9fa60b0/packages/stargate/src/signingstargateclient.ts#L280 @@ -94,7 +115,11 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ ): Promise { const txRaw = await this.groupSign(signerAddresses, messages, fee, memo); const txBytes = TxRaw.encode(txRaw).finish(); - return this.broadcastTx(txBytes, this.broadcastTimeoutMs, this.broadcastPollIntervalMs); + return this.broadcastTx( + txBytes, + this.broadcastTimeoutMs, + this.broadcastPollIntervalMs, + ); } // Reference: https://github.com/cosmos/cosmjs/blob/06fbc34f72f12c30a396c3ca296f80eca9fa60b0/packages/stargate/src/signingstargateclient.ts#L301 @@ -118,12 +143,18 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ accountNumber: accountNumber, sequence: sequence, chainId: chainId, - } - }) + }; + }), ); } - return this.groupSignDirect(signerAddresses, messages, fee, memo, signerDatas) + return this.groupSignDirect( + signerAddresses, + messages, + fee, + memo, + signerDatas, + ); } // Reference: https://github.com/cosmos/cosmjs/blob/06fbc34f72f12c30a396c3ca296f80eca9fa60b0/packages/stargate/src/signingstargateclient.ts#L370 @@ -132,7 +163,7 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ messages: readonly EncodeObject[], fee: StdFee, memo: string, - signerDatas: SignerData[] + signerDatas: SignerData[], ): Promise { // Retrieve accounts from signers const accounts: AccountData[] = await Promise.all( @@ -144,14 +175,21 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ throw new Error("Failed to retrieve account from signer"); } return account; - }) + }), ); // Build authInfos - const pubkeys = accounts.map((account) => encodePubkey(encodeSecp256k1Pubkey(account.pubkey))); + const pubkeys = accounts.map((account) => + encodePubkey(encodeSecp256k1Pubkey(account.pubkey)), + ); const sequences = signerDatas.map((signerData) => signerData.sequence); const gasLimit = Int53.fromString(fee.gas).toNumber(); - const authInfoBytes = this.makeAuthInfoBytesForGroupSigning(pubkeys, fee.amount, gasLimit, sequences); + const authInfoBytes = this.makeAuthInfoBytesForGroupSigning( + pubkeys, + fee.amount, + gasLimit, + sequences, + ); // Build an unsigned tx const txBodyEncodeObject: TxBodyEncodeObject = { @@ -159,20 +197,28 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ value: { messages: messages, memo: memo, - } + }, }; const txBodyBytes = this.registry.encode(txBodyEncodeObject); // Create signatures for each signer const signatures: Uint8Array[] = await Promise.all( signerDatas.map(async (signerData, i) => { - const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, signerData.chainId, signerData.accountNumber); + const signDoc = makeSignDoc( + txBodyBytes, + authInfoBytes, + signerData.chainId, + signerData.accountNumber, + ); const signer = this.signers[i]; assert(isOfflineDirectSigner(signer)); - const { signature } = await signer.signDirect(signerAddresses[i], signDoc); + const { signature } = await signer.signDirect( + signerAddresses[i], + signDoc, + ); return fromBase64(signature.signature); - }) + }), ); return TxRaw.fromPartial({ @@ -207,4 +253,4 @@ export class GroupSigningPanaceaClient extends SigningPanaceaClient{ }; return AuthInfo.encode(AuthInfo.fromPartial(authInfo)).finish(); } -} \ No newline at end of file +} diff --git a/src/client/index.ts b/src/client/index.ts index 1bf83a5..a9322ef 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,3 +1,3 @@ -export * from './group-signing-panacea-client'; -export * from './panacea-client'; -export * from './signing-panacea-client'; \ No newline at end of file +export * from "./group-signing-panacea-client"; +export * from "./panacea-client"; +export * from "./signing-panacea-client"; diff --git a/src/client/panacea-client.ts b/src/client/panacea-client.ts index 7ca22f0..9fd0b36 100644 --- a/src/client/panacea-client.ts +++ b/src/client/panacea-client.ts @@ -1,27 +1,32 @@ -import {createProtobufRpcClient, QueryClient, StargateClient, StargateClientOptions} from '@cosmjs/stargate'; -import {Topic} from '../proto/panacea/aol/v2/topic'; -import {Tendermint37Client} from '@cosmjs/tendermint-rpc/build/tendermint37'; -import {CometClient} from '@cosmjs/tendermint-rpc'; -import {PageRequest} from '../proto/cosmos/base/query/v1beta1/pagination'; +import { + createProtobufRpcClient, + QueryClient, + StargateClient, + StargateClientOptions, +} from "@cosmjs/stargate"; +import { Topic } from "../proto/panacea/aol/v2/topic"; +import { Tendermint37Client } from "@cosmjs/tendermint-rpc/build/tendermint37"; +import { CometClient } from "@cosmjs/tendermint-rpc"; +import { PageRequest } from "../proto/cosmos/base/query/v1beta1/pagination"; import { QueryClientImpl as AolQueryClientImpl, QueryTopicsResponse, QueryWritersResponse, -} from '../proto/panacea/aol/v2/query'; -import {Writer} from '../proto/panacea/aol/v2/writer'; -import {Record} from '../proto/panacea/aol/v2/record'; -import Long from 'long'; -import {DIDDocumentWithSeq} from "../proto/panacea/did/v2/did"; +} from "../proto/panacea/aol/v2/query"; +import { Writer } from "../proto/panacea/aol/v2/writer"; +import { Record } from "../proto/panacea/aol/v2/record"; +import Long from "long"; +import { DIDDocumentWithSeq } from "../proto/panacea/did/v2/did"; import { QueryClientImpl as PnftQueryClientImpl, QueryDenomsByOwnerResponse, QueryDenomsResponse, QueryPNFTsByDenomOwnerResponse, QueryPNFTsResponse, -} from '../proto/panacea/pnft/v2/query'; -import {QueryClientImpl as DidQueryClientImpl} from '../proto/panacea/did/v2/query'; -import {Denom} from '../proto/panacea/pnft/v2/denom'; -import {Pnft} from '../proto/panacea/pnft/v2/pnft'; +} from "../proto/panacea/pnft/v2/query"; +import { QueryClientImpl as DidQueryClientImpl } from "../proto/panacea/did/v2/query"; +import { Denom } from "../proto/panacea/pnft/v2/denom"; +import { Pnft } from "../proto/panacea/pnft/v2/pnft"; export class PanaceaClient extends StargateClient { private readonly aolQueryClient: AolQueryClientImpl; @@ -30,7 +35,7 @@ export class PanaceaClient extends StargateClient { constructor(tmClient: CometClient, options: StargateClientOptions) { super(tmClient, options); - const pbRpcClient = createProtobufRpcClient(new QueryClient(tmClient)) + const pbRpcClient = createProtobufRpcClient(new QueryClient(tmClient)); this.aolQueryClient = new AolQueryClientImpl(pbRpcClient); this.didQueryClient = new DidQueryClientImpl(pbRpcClient); this.pnftQueryClient = new PnftQueryClientImpl(pbRpcClient); @@ -44,79 +49,114 @@ export class PanaceaClient extends StargateClient { return new PanaceaClient(tmClient, {}); } - async getTopic(ownerAddress: string, topicName: string): Promise { - return fetchWithFallback(() => this.aolQueryClient.Topic({ - ownerAddress: ownerAddress, - topicName: topicName, - })) - .then((resp) => resp?.topic); + async getTopic( + ownerAddress: string, + topicName: string, + ): Promise { + return fetchWithFallback(() => + this.aolQueryClient.Topic({ + ownerAddress: ownerAddress, + topicName: topicName, + }), + ).then((resp) => resp?.topic); } - async getTopics(ownerAddress: string, pageRequest?: PageRequest): Promise { - return this.aolQueryClient.Topics({ownerAddress: ownerAddress, pagination: pageRequest}); + async getTopics( + ownerAddress: string, + pageRequest?: PageRequest, + ): Promise { + return this.aolQueryClient.Topics({ + ownerAddress: ownerAddress, + pagination: pageRequest, + }); } - async getRecord(ownerAddress: string, topicName: string, offset: number): Promise { - return fetchWithFallback(() => this.aolQueryClient.Record( - { + async getRecord( + ownerAddress: string, + topicName: string, + offset: number, + ): Promise { + return fetchWithFallback(() => + this.aolQueryClient.Record({ ownerAddress: ownerAddress, topicName: topicName, offset: new Long(offset), - })) - .then(res => res?.record); + }), + ).then((res) => res?.record); } - async getWriters(ownerAddress: string, topicName: string, pageRequest?: PageRequest): Promise { - return this.aolQueryClient.Writers({ownerAddress: ownerAddress, topicName: topicName, pagination: pageRequest}); - } - - async getWriter(ownerAddress: string, topicName: string, writerAddress: string): Promise { - return fetchWithFallback(() => this.aolQueryClient.Writer({ + async getWriters( + ownerAddress: string, + topicName: string, + pageRequest?: PageRequest, + ): Promise { + return this.aolQueryClient.Writers({ ownerAddress: ownerAddress, topicName: topicName, - writerAddress: writerAddress, - })) - .then(res => res?.writer); + pagination: pageRequest, + }); + } + + async getWriter( + ownerAddress: string, + topicName: string, + writerAddress: string, + ): Promise { + return fetchWithFallback(() => + this.aolQueryClient.Writer({ + ownerAddress: ownerAddress, + topicName: topicName, + writerAddress: writerAddress, + }), + ).then((res) => res?.writer); } async getDid(did: string): Promise { - return fetchWithFallback(() => this.didQueryClient.DID({ - didBase64: Buffer.from(did).toString('base64'), - })) - .then(res => res?.didDocumentWithSeq); + return fetchWithFallback(() => + this.didQueryClient.DID({ + didBase64: Buffer.from(did).toString("base64"), + }), + ).then((res) => res?.didDocumentWithSeq); } async getDenoms(pagination?: PageRequest): Promise { - return this.pnftQueryClient.Denoms({pagination}); + return this.pnftQueryClient.Denoms({ pagination }); } async getDenomsByOwner(owner: string): Promise { - return this.pnftQueryClient.DenomsByOwner({owner}) + return this.pnftQueryClient.DenomsByOwner({ owner }); } async getDenom(id: string): Promise { - return fetchWithFallback(() => this.pnftQueryClient.Denom({id})) - .then(res => res?.denom); + return fetchWithFallback(() => this.pnftQueryClient.Denom({ id })).then( + (res) => res?.denom, + ); } async getPnfts(denomId: string): Promise { - return this.pnftQueryClient.PNFTs({denomId}); + return this.pnftQueryClient.PNFTs({ denomId }); } - async getPnftsByOwner(denomId: string, owner: string): Promise { - return this.pnftQueryClient.PNFTsByDenomOwner({denomId, owner}); + async getPnftsByOwner( + denomId: string, + owner: string, + ): Promise { + return this.pnftQueryClient.PNFTsByDenomOwner({ denomId, owner }); } async getPnft(denomId: string, id: string): Promise { - return fetchWithFallback(() => this.pnftQueryClient.PNFT({denomId, id})) - .then(res => res?.pnft); + return fetchWithFallback(() => + this.pnftQueryClient.PNFT({ denomId, id }), + ).then((res) => res?.pnft); } } -async function fetchWithFallback(fetchFunc: () => Promise): Promise { +async function fetchWithFallback( + fetchFunc: () => Promise, +): Promise { try { return await fetchFunc(); } catch (error) { console.error(error); } -} \ No newline at end of file +} diff --git a/src/client/signing-panacea-client.ts b/src/client/signing-panacea-client.ts index ca27311..b93ba9a 100644 --- a/src/client/signing-panacea-client.ts +++ b/src/client/signing-panacea-client.ts @@ -6,19 +6,28 @@ import { SigningStargateClient, SigningStargateClientOptions, StdFee, -} from '@cosmjs/stargate'; -import {DirectSecp256k1HdWalletOptions, GeneratedType, OfflineSigner, Registry} from '@cosmjs/proto-signing'; -import {Tendermint37Client} from '@cosmjs/tendermint-rpc/build/tendermint37'; -import {PanaceaClient} from './panacea-client'; -import {CometClient} from '@cosmjs/tendermint-rpc'; +} from "@cosmjs/stargate"; +import { + DirectSecp256k1HdWalletOptions, + GeneratedType, + OfflineSigner, + Registry, +} from "@cosmjs/proto-signing"; +import { Tendermint37Client } from "@cosmjs/tendermint-rpc/build/tendermint37"; +import { PanaceaClient } from "./panacea-client"; +import { CometClient } from "@cosmjs/tendermint-rpc"; import { MsgAddRecordRequest, MsgAddWriterRequest, MsgCreateTopicRequest, MsgDeleteWriterRequest, -} from '../proto/panacea/aol/v2/tx'; -import {stringToPath} from '@cosmjs/crypto'; -import {MsgCreateDIDRequest, MsgDeactivateDIDRequest, MsgUpdateDIDRequest} from '../proto/panacea/did/v2/tx'; +} from "../proto/panacea/aol/v2/tx"; +import { stringToPath } from "@cosmjs/crypto"; +import { + MsgCreateDIDRequest, + MsgDeactivateDIDRequest, + MsgUpdateDIDRequest, +} from "../proto/panacea/did/v2/tx"; import { MsgBurnPNFTRequest, MsgCreateDenomRequest, @@ -27,61 +36,69 @@ import { MsgTransferDenomRequest, MsgTransferPNFTRequest, MsgUpdateDenomRequest, -} from '../proto/panacea/pnft/v2/tx'; +} from "../proto/panacea/pnft/v2/tx"; -export const panaceaDefaultGasPrice = GasPrice.fromString('5umed'); +export const panaceaDefaultGasPrice = GasPrice.fromString("5umed"); export const panaceaWalletOpts: Partial = { - hdPaths: [stringToPath('m/44\'/371\'/0\'/0/0')], - prefix: 'panacea', + hdPaths: [stringToPath("m/44'/371'/0'/0/0")], + prefix: "panacea", }; export interface Msg { - typeUrl: string, - value: T, + typeUrl: string; + value: T; } export class SigningPanaceaClient extends SigningStargateClient { - static msgTypeCreateTopic = '/panacea.aol.v2.MsgCreateTopicRequest'; - static msgTypeAddWriter = '/panacea.aol.v2.MsgAddWriterRequest'; - static msgTypeDeleteWriter = '/panacea.aol.v2.MsgDeleteWriterRequest'; - static msgTypeAddRecord = '/panacea.aol.v2.MsgAddRecordRequest'; - static msgTypeCreateDid = '/panacea.did.v2.MsgCreateDIDRequest'; - static msgTypeUpdateDid = '/panacea.did.v2.MsgUpdateDIDRequest'; - static msgTypeDeactivateDid = '/panacea.did.v2.MsgDeactivateDIDRequest'; - static msgTypeCreateDenom = '/panacea.pnft.v2.MsgCreateDenomRequest'; - static msgTypeUpdateDenom = '/panacea.pnft.v2.MsgUpdateDenomRequest'; - static msgTypeTransferDenom = '/panacea.pnft.v2.MsgTransferDenomRequest'; - static msgTypeDeleteDenom = '/panacea.pnft.v2.MsgDeleteDenomRequest'; - static msgTypeMintPnft = '/panacea.pnft.v2.MsgMintPNFTRequest'; - static msgTypeTransferPnft = '/panacea.pnft.v2.MsgTransferPNFTRequest'; - static msgTypeBurnPnft = '/panacea.pnft.v2.MsgBurnPNFTRequest'; - - private static panaceaRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [ - [SigningPanaceaClient.msgTypeCreateTopic, MsgCreateTopicRequest], - [SigningPanaceaClient.msgTypeAddWriter, MsgAddWriterRequest], - [SigningPanaceaClient.msgTypeDeleteWriter, MsgDeleteWriterRequest], - [SigningPanaceaClient.msgTypeAddRecord, MsgAddRecordRequest], - [SigningPanaceaClient.msgTypeCreateDid, MsgCreateDIDRequest], - [SigningPanaceaClient.msgTypeUpdateDid, MsgUpdateDIDRequest], - [SigningPanaceaClient.msgTypeDeactivateDid, MsgDeactivateDIDRequest], - [SigningPanaceaClient.msgTypeCreateDenom, MsgCreateDenomRequest], - [SigningPanaceaClient.msgTypeUpdateDenom, MsgUpdateDenomRequest], - [SigningPanaceaClient.msgTypeTransferDenom, MsgTransferDenomRequest], - [SigningPanaceaClient.msgTypeDeleteDenom, MsgDeleteDenomRequest], - [SigningPanaceaClient.msgTypeMintPnft, MsgMintPNFTRequest], - [SigningPanaceaClient.msgTypeTransferPnft, MsgTransferPNFTRequest], - [SigningPanaceaClient.msgTypeBurnPnft, MsgBurnPNFTRequest], - ]; - - constructor(tmClient: CometClient | undefined, signer: OfflineSigner, options: SigningStargateClientOptions) { + static msgTypeCreateTopic = "/panacea.aol.v2.MsgCreateTopicRequest"; + static msgTypeAddWriter = "/panacea.aol.v2.MsgAddWriterRequest"; + static msgTypeDeleteWriter = "/panacea.aol.v2.MsgDeleteWriterRequest"; + static msgTypeAddRecord = "/panacea.aol.v2.MsgAddRecordRequest"; + static msgTypeCreateDid = "/panacea.did.v2.MsgCreateDIDRequest"; + static msgTypeUpdateDid = "/panacea.did.v2.MsgUpdateDIDRequest"; + static msgTypeDeactivateDid = "/panacea.did.v2.MsgDeactivateDIDRequest"; + static msgTypeCreateDenom = "/panacea.pnft.v2.MsgCreateDenomRequest"; + static msgTypeUpdateDenom = "/panacea.pnft.v2.MsgUpdateDenomRequest"; + static msgTypeTransferDenom = "/panacea.pnft.v2.MsgTransferDenomRequest"; + static msgTypeDeleteDenom = "/panacea.pnft.v2.MsgDeleteDenomRequest"; + static msgTypeMintPnft = "/panacea.pnft.v2.MsgMintPNFTRequest"; + static msgTypeTransferPnft = "/panacea.pnft.v2.MsgTransferPNFTRequest"; + static msgTypeBurnPnft = "/panacea.pnft.v2.MsgBurnPNFTRequest"; + + private static panaceaRegistryTypes: ReadonlyArray<[string, GeneratedType]> = + [ + [SigningPanaceaClient.msgTypeCreateTopic, MsgCreateTopicRequest], + [SigningPanaceaClient.msgTypeAddWriter, MsgAddWriterRequest], + [SigningPanaceaClient.msgTypeDeleteWriter, MsgDeleteWriterRequest], + [SigningPanaceaClient.msgTypeAddRecord, MsgAddRecordRequest], + [SigningPanaceaClient.msgTypeCreateDid, MsgCreateDIDRequest], + [SigningPanaceaClient.msgTypeUpdateDid, MsgUpdateDIDRequest], + [SigningPanaceaClient.msgTypeDeactivateDid, MsgDeactivateDIDRequest], + [SigningPanaceaClient.msgTypeCreateDenom, MsgCreateDenomRequest], + [SigningPanaceaClient.msgTypeUpdateDenom, MsgUpdateDenomRequest], + [SigningPanaceaClient.msgTypeTransferDenom, MsgTransferDenomRequest], + [SigningPanaceaClient.msgTypeDeleteDenom, MsgDeleteDenomRequest], + [SigningPanaceaClient.msgTypeMintPnft, MsgMintPNFTRequest], + [SigningPanaceaClient.msgTypeTransferPnft, MsgTransferPNFTRequest], + [SigningPanaceaClient.msgTypeBurnPnft, MsgBurnPNFTRequest], + ]; + + constructor( + tmClient: CometClient | undefined, + signer: OfflineSigner, + options: SigningStargateClientOptions, + ) { // Before calling super(), set Panacea default options if not specified. if (!options.gasPrice) { - options = {...options, gasPrice: panaceaDefaultGasPrice}; + options = { ...options, gasPrice: panaceaDefaultGasPrice }; } if (!options.registry) { - const registry = new Registry([...defaultRegistryTypes, ...SigningPanaceaClient.panaceaRegistryTypes]); - options = {...options, registry: registry}; + const registry = new Registry([ + ...defaultRegistryTypes, + ...SigningPanaceaClient.panaceaRegistryTypes, + ]); + options = { ...options, registry: registry }; } super(tmClient, signer, options); @@ -91,12 +108,19 @@ export class SigningPanaceaClient extends SigningStargateClient { * Creates a SigningPanaceaClient. * Note that it is important to specify options.gasPrice. If not, the default gas price will be used. */ - static async connectWithSigner(endpoint: string, signer: OfflineSigner, options: SigningStargateClientOptions = {}) { + static async connectWithSigner( + endpoint: string, + signer: OfflineSigner, + options: SigningStargateClientOptions = {}, + ) { const tmClient = await Tendermint37Client.connect(endpoint); return new SigningPanaceaClient(tmClient, signer, options); } - static async offline(signer: OfflineSigner, options: SigningStargateClientOptions = {}): Promise { + static async offline( + signer: OfflineSigner, + options: SigningStargateClientOptions = {}, + ): Promise { return new SigningPanaceaClient(undefined, signer, options); } @@ -107,133 +131,175 @@ export class SigningPanaceaClient extends SigningStargateClient { return new PanaceaClient(this.forceGetCometClient(), {}); } - async createTopic(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeCreateTopic, - value: MsgCreateTopicRequest.create(request), - }; + async createTopic( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeCreateTopic, + value: MsgCreateTopicRequest.create(request), + }; return this.signAndBroadcast(request.ownerAddress!, [msg], fee, memo); } - async addWriter(request: Partial, fee: StdFee | 'auto', memo?: string) { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeAddWriter, - value: MsgAddWriterRequest.create(request), - }; + async addWriter( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ) { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeAddWriter, + value: MsgAddWriterRequest.create(request), + }; return this.signAndBroadcast(request.ownerAddress!, [msg], fee, memo); } - async deleteWriter(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeDeleteWriter, - value: MsgDeleteWriterRequest.create(request), - }; + async deleteWriter( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeDeleteWriter, + value: MsgDeleteWriterRequest.create(request), + }; return this.signAndBroadcast(request.ownerAddress!, [msg], fee, memo); } - async addRecord(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeAddRecord, - value: MsgAddRecordRequest.create(request), - }; + async addRecord( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeAddRecord, + value: MsgAddRecordRequest.create(request), + }; return this.signAndBroadcast(request.writerAddress!, [msg], fee, memo); } - async createDid(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeCreateDid, - value: MsgCreateDIDRequest.create(request), - }; + async createDid( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeCreateDid, + value: MsgCreateDIDRequest.create(request), + }; return this.signAndBroadcast(request.fromAddress!, [msg], fee, memo); } - async updateDid(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeUpdateDid, - value: MsgUpdateDIDRequest.create(request), - }; + async updateDid( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeUpdateDid, + value: MsgUpdateDIDRequest.create(request), + }; return this.signAndBroadcast(request.fromAddress!, [msg], fee, memo); } - async deactivateDid(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeDeactivateDid, - value: MsgDeactivateDIDRequest.create(request), - }; + async deactivateDid( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeDeactivateDid, + value: MsgDeactivateDIDRequest.create(request), + }; return this.signAndBroadcast(request.fromAddress!, [msg], fee, memo); } - async createDenom(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeCreateDenom, - value: MsgCreateDenomRequest.create(request), - }; + async createDenom( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeCreateDenom, + value: MsgCreateDenomRequest.create(request), + }; return this.signAndBroadcast(request.creator!, [msg], fee, memo); } - async updateDenom(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeUpdateDenom, - value: MsgUpdateDenomRequest.create(request), - }; + async updateDenom( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeUpdateDenom, + value: MsgUpdateDenomRequest.create(request), + }; return this.signAndBroadcast(request.updater!, [msg], fee, memo); } - async transferDenom(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeTransferDenom, - value: MsgTransferDenomRequest.create(request), - }; + async transferDenom( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeTransferDenom, + value: MsgTransferDenomRequest.create(request), + }; return this.signAndBroadcast(request.sender!, [msg], fee, memo); } - async deleteDenom(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeDeleteDenom, - value: MsgDeleteDenomRequest.create(request), - }; + async deleteDenom( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeDeleteDenom, + value: MsgDeleteDenomRequest.create(request), + }; return this.signAndBroadcast(request.remover!, [msg], fee, memo); } - async mintPNFT(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeMintPnft, - value: MsgMintPNFTRequest.create(request), - }; + async mintPNFT( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeMintPnft, + value: MsgMintPNFTRequest.create(request), + }; return this.signAndBroadcast(request.creator!, [msg], fee, memo); } - async transferPNFT(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeTransferPnft, - value: MsgTransferPNFTRequest.create(request), - }; + async transferPNFT( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeTransferPnft, + value: MsgTransferPNFTRequest.create(request), + }; return this.signAndBroadcast(request.sender!, [msg], fee, memo); } - async burnPNFT(request: Partial, fee: StdFee | 'auto', memo?: string): Promise { - const msg: Msg = - { - typeUrl: SigningPanaceaClient.msgTypeBurnPnft, - value: MsgBurnPNFTRequest.create(request), - }; + async burnPNFT( + request: Partial, + fee: StdFee | "auto", + memo?: string, + ): Promise { + const msg: Msg = { + typeUrl: SigningPanaceaClient.msgTypeBurnPnft, + value: MsgBurnPNFTRequest.create(request), + }; return this.signAndBroadcast(request.burner!, [msg], fee, memo); } createFee(gasLimit: number): StdFee { - return calculateFee(gasLimit, panaceaDefaultGasPrice) + return calculateFee(gasLimit, panaceaDefaultGasPrice); } -} \ No newline at end of file +} diff --git a/src/crypto/index.ts b/src/crypto/index.ts index 4b54be3..d894a71 100644 --- a/src/crypto/index.ts +++ b/src/crypto/index.ts @@ -1 +1 @@ -export * from './secp256k1'; +export * from "./secp256k1"; diff --git a/src/crypto/secp256k1.ts b/src/crypto/secp256k1.ts index e0aa32e..c9e81cf 100644 --- a/src/crypto/secp256k1.ts +++ b/src/crypto/secp256k1.ts @@ -1,14 +1,20 @@ import ecc from "secp256k1"; import { randomBytes } from "crypto"; -import { Bip39, EnglishMnemonic, Slip10, Slip10Curve, Slip10RawIndex } from "@cosmjs/crypto" -import * as jose from 'jose' +import { + Bip39, + EnglishMnemonic, + Slip10, + Slip10Curve, + Slip10RawIndex, +} from "@cosmjs/crypto"; +import * as jose from "jose"; import { base64url } from "jose"; export class Secp256k1 { static generatePrivateKey(): Uint8Array { - let privKey + let privKey; do { - privKey = randomBytes(32) + privKey = randomBytes(32); } while (!ecc.privateKeyVerify(privKey)); return privKey; } @@ -28,7 +34,9 @@ export class Secp256k1 { // Convert a raw private key to JWK static convertPrivateKeyToJWK(privKey: Uint8Array): jose.JWK { - const jwk = this.convertPublicKeyToJWK(Secp256k1.getPublicKeyUncompressed(privKey)); + const jwk = this.convertPublicKeyToJWK( + Secp256k1.getPublicKeyUncompressed(privKey), + ); jwk.d = base64url.encode(privKey); return jwk; } @@ -47,7 +55,10 @@ export class Secp256k1 { return ecc.ecdsaSign(data32, privKey).signature; } - static async parseMnemonicToPrivateKey(mnemonic: string, hdPath: readonly Slip10RawIndex[]): Promise { + static async parseMnemonicToPrivateKey( + mnemonic: string, + hdPath: readonly Slip10RawIndex[], + ): Promise { const mnemonicChecked = new EnglishMnemonic(mnemonic); const seed = await Bip39.mnemonicToSeed(mnemonicChecked, ""); return Slip10.derivePath(Slip10Curve.Secp256k1, seed, hdPath).privkey; diff --git a/src/did/index.ts b/src/did/index.ts index 93ca369..499db9a 100644 --- a/src/did/index.ts +++ b/src/did/index.ts @@ -1,2 +1,2 @@ -export * from './util'; -export * from './jwt'; \ No newline at end of file +export * from "./util"; +export * from "./jwt"; diff --git a/src/did/jwt.spec.ts b/src/did/jwt.spec.ts index 8d18164..d689c77 100644 --- a/src/did/jwt.spec.ts +++ b/src/did/jwt.spec.ts @@ -5,7 +5,6 @@ import { DIDDocument } from "../proto/panacea/did/v2/did"; import { sleep } from "@cosmjs/utils"; describe("DidAuthJwt", () => { - let privKey: Uint8Array; let didDocument: DIDDocument; const challenge = "this is a challenge"; @@ -17,14 +16,14 @@ describe("DidAuthJwt", () => { didDocument = { contexts: { - values: [ 'https://www.w3.org/ns/did/v1' ], + values: ["https://www.w3.org/ns/did/v1"], }, id: did, controller: undefined, verificationMethods: [ { id: `${did}#key1`, - type: 'EcdsaSecp256k1VerificationKey2019', + type: "EcdsaSecp256k1VerificationKey2019", controller: did, publicKeyBase58: DidUtil.getPublicKeyBase58(pubKey), }, @@ -33,18 +32,18 @@ describe("DidAuthJwt", () => { { verificationMethodId: `${did}#key1`, verificationMethod: undefined, - } + }, ], assertionMethods: [ { verificationMethodId: undefined, verificationMethod: { id: `${did}#key2`, - type: 'EcdsaSecp256k1VerificationKey2019', + type: "EcdsaSecp256k1VerificationKey2019", controller: did, publicKeyBase58: DidUtil.getPublicKeyBase58(pubKey), }, - } + }, ], keyAgreements: [], capabilityInvocations: [], @@ -54,7 +53,13 @@ describe("DidAuthJwt", () => { }); it("issue and verify", async () => { - const jwt = await DidAuthJwt.issue(didDocument.id, privKey, didDocument.authentications[0].verificationMethodId!, challenge, 3); + const jwt = await DidAuthJwt.issue( + didDocument.id, + privKey, + didDocument.authentications[0].verificationMethodId!, + challenge, + 3, + ); await expect(async () => { await DidAuthJwt.verify(jwt, didDocument, challenge); @@ -69,7 +74,13 @@ describe("DidAuthJwt", () => { it("verify: unexpected challenge", async () => { const wrongChallenge = "dummy"; - const jwt = await DidAuthJwt.issue(didDocument.id, privKey, didDocument.authentications[0].verificationMethodId!, wrongChallenge, 3); + const jwt = await DidAuthJwt.issue( + didDocument.id, + privKey, + didDocument.authentications[0].verificationMethodId!, + wrongChallenge, + 3, + ); await expect(async () => { await DidAuthJwt.verify(jwt, didDocument, challenge); @@ -77,7 +88,13 @@ describe("DidAuthJwt", () => { }); it("verify: expired", async () => { - const jwt = await DidAuthJwt.issue(didDocument.id, privKey, didDocument.authentications[0].verificationMethodId!, challenge, 0); + const jwt = await DidAuthJwt.issue( + didDocument.id, + privKey, + didDocument.authentications[0].verificationMethodId!, + challenge, + 0, + ); await sleep(1000); @@ -88,7 +105,13 @@ describe("DidAuthJwt", () => { it("verify: signed with wrong private key", async () => { const anotherPrivKey = await Secp256k1.generatePrivateKey(); - const jwt = await DidAuthJwt.issue(didDocument.id, anotherPrivKey, didDocument.authentications[0].verificationMethodId!, challenge, 3); + const jwt = await DidAuthJwt.issue( + didDocument.id, + anotherPrivKey, + didDocument.authentications[0].verificationMethodId!, + challenge, + 3, + ); await expect(async () => { await DidAuthJwt.verify(jwt, didDocument, challenge); @@ -96,8 +119,15 @@ describe("DidAuthJwt", () => { }); it("verify: wrong verification method ID", async () => { - const wrongMethodId = didDocument.assertionMethods[0].verificationMethod!.id! // use assertionMethods instead of authentications - const jwt = await DidAuthJwt.issue(didDocument.id, privKey, wrongMethodId, challenge, 3); + const wrongMethodId = + didDocument.assertionMethods[0].verificationMethod!.id!; // use assertionMethods instead of authentications + const jwt = await DidAuthJwt.issue( + didDocument.id, + privKey, + wrongMethodId, + challenge, + 3, + ); await expect(async () => { await DidAuthJwt.verify(jwt, didDocument, challenge); diff --git a/src/did/jwt.ts b/src/did/jwt.ts index b72c2a5..1ecbb9a 100644 --- a/src/did/jwt.ts +++ b/src/did/jwt.ts @@ -1,19 +1,28 @@ import * as jose from "jose"; import { DIDDocument } from "../proto/panacea/did/v2/did"; -import {Secp256k1} from "../crypto/secp256k1"; +import { Secp256k1 } from "../crypto"; import { DidUtil } from "./util"; -const bs58 = require('bs58'); +import bs58 from "bs58"; export class DidAuthJwt { private static readonly JwtType = "JWT"; private static readonly JwtAlgo = "ES256K"; - static async issue(did: string, privKey: Uint8Array, verificationMethodId: string, challenge: string, expirationSec: number): Promise { - const key = await jose.importJWK(Secp256k1.convertPrivateKeyToJWK(privKey), "ES256K") + static async issue( + did: string, + privKey: Uint8Array, + verificationMethodId: string, + challenge: string, + expirationSec: number, + ): Promise { + const key = await jose.importJWK( + Secp256k1.convertPrivateKeyToJWK(privKey), + "ES256K", + ); const payload = { - "verificationMethod": verificationMethodId, - "challenge": challenge, + verificationMethod: verificationMethodId, + challenge: challenge, }; const now = this.epoch(new Date()); @@ -27,7 +36,11 @@ export class DidAuthJwt { .sign(key); } - static async verify(jwt: string, didDocument: DIDDocument, challenge: string) { + static async verify( + jwt: string, + didDocument: DIDDocument, + challenge: string, + ) { const payload = await jose.decodeJwt(jwt); if (payload.challenge !== challenge) { @@ -40,8 +53,13 @@ export class DidAuthJwt { didDocument.verificationMethods, didDocument.authentications, ); - const pubKey = Secp256k1.uncompressPublicKey(bs58.decode(vm.publicKeyBase58)); - const key = await jose.importJWK(Secp256k1.convertPublicKeyToJWK(pubKey), "ES256K") + const pubKey = Secp256k1.uncompressPublicKey( + bs58.decode(vm.publicKeyBase58), + ); + const key = await jose.importJWK( + Secp256k1.convertPublicKeyToJWK(pubKey), + "ES256K", + ); await jose.jwtVerify(jwt, key, { typ: this.JwtType, diff --git a/src/did/util.spec.ts b/src/did/util.spec.ts index 0535fc5..4c3c2f4 100644 --- a/src/did/util.spec.ts +++ b/src/did/util.spec.ts @@ -1,5 +1,5 @@ import { DidUtil } from "./util"; -import {Secp256k1} from "../crypto/secp256k1"; +import { Secp256k1 } from "../crypto/secp256k1"; describe("DidUtil", () => { it("findVerificationMethod", async () => { @@ -10,14 +10,14 @@ describe("DidUtil", () => { const didDocument = { contexts: { - values: [ 'https://www.w3.org/ns/did/v1' ], + values: ["https://www.w3.org/ns/did/v1"], }, id: did, controller: undefined, verificationMethods: [ { id: verificationMethodId, - type: 'EcdsaSecp256k1VerificationKey2019', + type: "EcdsaSecp256k1VerificationKey2019", controller: did, publicKeyBase58: DidUtil.getPublicKeyBase58(pubKey), }, @@ -26,7 +26,7 @@ describe("DidUtil", () => { { verificationMethodId: verificationMethodId, verificationMethod: undefined, - } + }, ], assertionMethods: [], keyAgreements: [], @@ -35,18 +35,29 @@ describe("DidUtil", () => { services: [], }; - let vm = DidUtil.findVerificationMethod(verificationMethodId, didDocument.verificationMethods) + let vm = DidUtil.findVerificationMethod( + verificationMethodId, + didDocument.verificationMethods, + ); expect(vm).toStrictEqual(didDocument.verificationMethods[0]); - vm = DidUtil.findVerificationMethod(verificationMethodId, didDocument.verificationMethods, didDocument.authentications); + vm = DidUtil.findVerificationMethod( + verificationMethodId, + didDocument.verificationMethods, + didDocument.authentications, + ); expect(vm).toStrictEqual(didDocument.verificationMethods[0]); expect(() => { - DidUtil.findVerificationMethod("dummy", didDocument.verificationMethods) + DidUtil.findVerificationMethod("dummy", didDocument.verificationMethods); }).toThrow(`unable to find verification method: dummy`); expect(() => { - DidUtil.findVerificationMethod(verificationMethodId, didDocument.verificationMethods, didDocument.assertionMethods); + DidUtil.findVerificationMethod( + verificationMethodId, + didDocument.verificationMethods, + didDocument.assertionMethods, + ); }).toThrow(`unable to find verification method: ${verificationMethodId}`); }); }); diff --git a/src/did/util.ts b/src/did/util.ts index d007b78..2e302d6 100644 --- a/src/did/util.ts +++ b/src/did/util.ts @@ -1,5 +1,10 @@ import { sha256 } from "@cosmjs/crypto"; -import { DIDDocument, DataWithSeq, VerificationRelationship, VerificationMethod } from "../proto/panacea/did/v2/did"; +import { + DIDDocument, + DataWithSeq, + VerificationRelationship, + VerificationMethod, +} from "../proto/panacea/did/v2/did"; import Long from "long"; import { Secp256k1 } from "../crypto"; import bs58 from "bs58"; @@ -13,15 +18,26 @@ export class DidUtil { return bs58.encode(pubKeyCompressed); } - static signDidDocument(privKey: Uint8Array, didDocument: DIDDocument, sequence: Long = Long.fromInt(0)): Uint8Array { + static signDidDocument( + privKey: Uint8Array, + didDocument: DIDDocument, + sequence: Long = Long.fromInt(0), + ): Uint8Array { const dataWithSeq: DataWithSeq = { data: DIDDocument.encode(didDocument).finish(), sequence: sequence, }; - return Secp256k1.sign(sha256(DataWithSeq.encode(dataWithSeq).finish()), privKey); + return Secp256k1.sign( + sha256(DataWithSeq.encode(dataWithSeq).finish()), + privKey, + ); } - static signDid(privKey: Uint8Array, did: string, sequence: Long = Long.fromInt(0)): Uint8Array { + static signDid( + privKey: Uint8Array, + did: string, + sequence: Long = Long.fromInt(0), + ): Uint8Array { const didDocument: DIDDocument = { contexts: undefined, id: did, @@ -33,7 +49,7 @@ export class DidUtil { capabilityInvocations: [], capabilityDelegations: [], services: [], - } + }; return this.signDidDocument(privKey, didDocument, sequence); } @@ -42,10 +58,17 @@ export class DidUtil { // In this case, 'methods' are used as a reference for 'relationships'. // If 'relationships' are not specified, find the verification method only from 'methods'. // If the verification method is not found, throw an error. - static findVerificationMethod(id: string, methods: VerificationMethod[], relationships?: VerificationRelationship[]): VerificationMethod { + static findVerificationMethod( + id: string, + methods: VerificationMethod[], + relationships?: VerificationRelationship[], + ): VerificationMethod { if (relationships) { for (const relationship of relationships) { - if (relationship.verificationMethod !== undefined && relationship.verificationMethod.id === id) { + if ( + relationship.verificationMethod !== undefined && + relationship.verificationMethod.id === id + ) { return relationship.verificationMethod; } if (relationship.verificationMethodId === id) { diff --git a/src/index.ts b/src/index.ts index d636b40..8a31369 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ -export * from './crypto'; -export * from './did'; -export * from './client'; +export * from "./crypto"; +export * from "./did"; +export * from "./client"; diff --git a/yarn.lock b/yarn.lock index 13b56b6..b50a4b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -418,6 +423,57 @@ resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.32.3.tgz#5dcaee6dd7cc846cdc073e9a7a7f63242f5f7e31" integrity sha512-WCZK4yksj2hBDz4w7xFZQTRZQ/RJhBX26uFHmmQFIcNUUVAihrLO+RerqJgk0dZqC42wstM9pEUQGtPmLcIYvg== +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== + +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" + integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -663,6 +719,27 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -802,6 +879,11 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/json-schema@^7.0.12": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/long@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" @@ -821,6 +903,11 @@ dependencies: "@types/node" "*" +"@types/semver@^7.5.0": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + "@types/stack-utils@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" @@ -843,6 +930,117 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/eslint-plugin@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.2.0.tgz#5a5fcad1a7baed85c10080d71ad901f98c38d5b7" + integrity sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "7.2.0" + "@typescript-eslint/type-utils" "7.2.0" + "@typescript-eslint/utils" "7.2.0" + "@typescript-eslint/visitor-keys" "7.2.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.2.0.tgz#44356312aea8852a3a82deebdacd52ba614ec07a" + integrity sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg== + dependencies: + "@typescript-eslint/scope-manager" "7.2.0" + "@typescript-eslint/types" "7.2.0" + "@typescript-eslint/typescript-estree" "7.2.0" + "@typescript-eslint/visitor-keys" "7.2.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz#cfb437b09a84f95a0930a76b066e89e35d94e3da" + integrity sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg== + dependencies: + "@typescript-eslint/types" "7.2.0" + "@typescript-eslint/visitor-keys" "7.2.0" + +"@typescript-eslint/type-utils@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz#7be5c30e9b4d49971b79095a1181324ef6089a19" + integrity sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA== + dependencies: + "@typescript-eslint/typescript-estree" "7.2.0" + "@typescript-eslint/utils" "7.2.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/types@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.2.0.tgz#0feb685f16de320e8520f13cca30779c8b7c403f" + integrity sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA== + +"@typescript-eslint/typescript-estree@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz#5beda2876c4137f8440c5a84b4f0370828682556" + integrity sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA== + dependencies: + "@typescript-eslint/types" "7.2.0" + "@typescript-eslint/visitor-keys" "7.2.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.2.0.tgz#fc8164be2f2a7068debb4556881acddbf0b7ce2a" + integrity sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "7.2.0" + "@typescript-eslint/types" "7.2.0" + "@typescript-eslint/typescript-estree" "7.2.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz#5035f177752538a5750cca1af6044b633610bf9e" + integrity sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A== + dependencies: + "@typescript-eslint/types" "7.2.0" + eslint-visitor-keys "^3.4.1" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -889,6 +1087,16 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1001,6 +1209,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -1184,7 +1399,7 @@ create-jest@^29.7.0: jest-util "^29.7.0" prompts "^2.0.1" -cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -1193,7 +1408,7 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1205,6 +1420,11 @@ dedent@^1.0.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + deepmerge@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -1248,6 +1468,20 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + dprint-node@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/dprint-node/-/dprint-node-1.0.8.tgz#a02470722d8208a7d7eb3704328afda1d6758625" @@ -1317,11 +1551,106 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.57.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -1353,11 +1682,39 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + fb-watchman@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" @@ -1365,6 +1722,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1380,6 +1744,28 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + follow-redirects@^1.15.4: version "1.15.5" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" @@ -1440,6 +1826,20 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -1457,6 +1857,13 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + globalthis@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -1464,6 +1871,18 @@ globalthis@^1.0.1: dependencies: define-properties "^1.1.3" +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -1476,6 +1895,11 @@ graceful-fs@^4.2.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1537,6 +1961,19 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -1575,6 +2012,11 @@ is-core-module@^2.13.0: dependencies: hasown "^2.0.0" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -1585,11 +2027,23 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" @@ -2034,21 +2488,50 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -2059,6 +2542,14 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + libsodium-sumo@^0.7.13: version "0.7.13" resolved "https://registry.yarnpkg.com/libsodium-sumo/-/libsodium-sumo-0.7.13.tgz#533b97d2be44b1277e59c1f9f60805978ac5542d" @@ -2083,11 +2574,23 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + long@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -2136,6 +2639,11 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -2171,7 +2679,14 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -2239,6 +2754,18 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -2246,7 +2773,7 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.1.0: +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -2260,11 +2787,25 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -2295,6 +2836,11 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -2317,6 +2863,16 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== + pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -2376,11 +2932,21 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + pure-rand@^6.0.0: version "6.0.4" resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + react-is@^18.0.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" @@ -2403,6 +2969,11 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve-from@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" @@ -2422,6 +2993,25 @@ resolve@^1.20.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + secp256k1@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.0.tgz#be6f0c8c7722e2481e9773336d351de8cddd12f7" @@ -2574,6 +3164,11 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -2591,6 +3186,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +ts-api-utils@^1.0.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + ts-jest@^29.1.2: version "29.1.2" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" @@ -2630,11 +3230,23 @@ ts-proto@^1.169.1: ts-poet "^6.7.0" ts-proto-descriptors "1.15.0" +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -2658,6 +3270,13 @@ update-browserslist-db@^1.0.13: escalade "^3.1.1" picocolors "^1.0.0" +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + uuid@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"