From d7821587980532824319d5d6882b90311a1576fc Mon Sep 17 00:00:00 2001 From: rabbyweb3team001 Date: Tue, 20 Aug 2024 16:11:54 +0800 Subject: [PATCH] add rabby wallet --- packages/rabby-wallet/.babelrc | 10 + packages/rabby-wallet/.eslintrc.json | 18 ++ packages/rabby-wallet/README.md | 70 ++++++ packages/rabby-wallet/assets/rabby-wallet.png | Bin 0 -> 21395 bytes packages/rabby-wallet/jest.config.ts | 16 ++ packages/rabby-wallet/package.json | 24 ++ packages/rabby-wallet/project.json | 56 +++++ packages/rabby-wallet/src/index.ts | 2 + packages/rabby-wallet/src/lib/icon.ts | 1 + .../src/lib/injected-rabby-wallet.ts | 73 ++++++ .../rabby-wallet/src/lib/rabby-wallet.spec.ts | 131 ++++++++++ packages/rabby-wallet/src/lib/rabby-wallet.ts | 236 ++++++++++++++++++ packages/rabby-wallet/tsconfig.json | 20 ++ packages/rabby-wallet/tsconfig.lib.json | 10 + packages/rabby-wallet/tsconfig.spec.json | 9 + 15 files changed, 676 insertions(+) create mode 100644 packages/rabby-wallet/.babelrc create mode 100644 packages/rabby-wallet/.eslintrc.json create mode 100644 packages/rabby-wallet/README.md create mode 100644 packages/rabby-wallet/assets/rabby-wallet.png create mode 100644 packages/rabby-wallet/jest.config.ts create mode 100644 packages/rabby-wallet/package.json create mode 100644 packages/rabby-wallet/project.json create mode 100644 packages/rabby-wallet/src/index.ts create mode 100644 packages/rabby-wallet/src/lib/icon.ts create mode 100644 packages/rabby-wallet/src/lib/injected-rabby-wallet.ts create mode 100644 packages/rabby-wallet/src/lib/rabby-wallet.spec.ts create mode 100644 packages/rabby-wallet/src/lib/rabby-wallet.ts create mode 100644 packages/rabby-wallet/tsconfig.json create mode 100644 packages/rabby-wallet/tsconfig.lib.json create mode 100644 packages/rabby-wallet/tsconfig.spec.json diff --git a/packages/rabby-wallet/.babelrc b/packages/rabby-wallet/.babelrc new file mode 100644 index 000000000..b63f0528f --- /dev/null +++ b/packages/rabby-wallet/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + [ + "@nrwl/js/babel", + { + "useBuiltIns": "usage" + } + ] + ] +} diff --git a/packages/rabby-wallet/.eslintrc.json b/packages/rabby-wallet/.eslintrc.json new file mode 100644 index 000000000..9d9c0db55 --- /dev/null +++ b/packages/rabby-wallet/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/packages/rabby-wallet/README.md b/packages/rabby-wallet/README.md new file mode 100644 index 000000000..c6d2d006a --- /dev/null +++ b/packages/rabby-wallet/README.md @@ -0,0 +1,70 @@ +# @near-wallet-selector/rabby-wallet + +This is the [Rabby Wallet](https://chromewebstore.google.com/detail/rabby-wallet/acmacodkjbdgmoleebolmdjonilkdbch) package for NEAR Wallet Selector. + +## Install Rabby Wallet + +- [Chrome](https://chromewebstore.google.com/detail/rabby-wallet/acmacodkjbdgmoleebolmdjonilkdbch) + + +## Installation and Usage + +The easiest way to use this package is to install it from the NPM registry, this package requires `near-api-js` v1.0.0 or above: + +```bash +# Using Yarn +yarn add near-api-js + +# Using NPM. +npm install near-api-js +``` +```bash +# Using Yarn +yarn add @near-wallet-selector/rabby-wallet + +# Using NPM. +npm install @near-wallet-selector/rabby-wallet +``` + +Then use it in your dApp: + +```ts +import { setupWalletSelector } from "@near-wallet-selector/core"; +import { setupRabbyWallet } from "@near-wallet-selector/rabby-wallet"; + +// Rabby Wallet for Wallet Selector can be setup without any params or it can take few optional params, see options below. +const rabbyWallet = setupRabbyWallet({ + iconUrl: "https://" // optional +}); + +const selector = await setupWalletSelector({ + network: "mainnet", // Rabby Wallet only supports NEAR Mainnet at the moment. + modules: [rabbyWallet], +}); +``` + +## Options + +- `iconUrl`: (`string?`): Image URL for the icon shown in the modal. This can also be a relative path or base64 encoded image. Defaults is `./assets/rabby-wallet.png`. +- `deprecated`: (`boolean?`): Deprecated is optional. Default is `false`. + +## Assets + +Assets such as icons can be found in the `/assets` directory of the package. Below is an example using Webpack: + +```ts +import { setupRabbyWallet } from "@near-wallet-selector/rabby-wallet"; +import rabbyIconUrl from "@near-wallet-selector/rabby-wallet/assets/rabby-wallet.png"; + +const rabbyWallet = setupRabbyWallet({ + iconUrl: rabbyIconUrl +}); +``` + +## Tip + +Rabby Wallet only supports NEAR Mainnet at the moment. + +## License + +This repository is distributed under the terms of both the MIT license and the Apache License (Version 2.0). diff --git a/packages/rabby-wallet/assets/rabby-wallet.png b/packages/rabby-wallet/assets/rabby-wallet.png new file mode 100644 index 0000000000000000000000000000000000000000..1a8514fb85ae4fe4b1ad5c062208011d05337bd0 GIT binary patch literal 21395 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/tsconfig.spec.json", + }, + ], + }, + moduleFileExtensions: ["ts", "tsx", "js", "jsx"], + coverageDirectory: "../../coverage/packages/rabby-wallet", +}; diff --git a/packages/rabby-wallet/package.json b/packages/rabby-wallet/package.json new file mode 100644 index 000000000..218f160f6 --- /dev/null +++ b/packages/rabby-wallet/package.json @@ -0,0 +1,24 @@ +{ + "name": "@near-wallet-selector/rabby-wallet", + "version": "8.9.12", + "description": "rabby Wallet package for NEAR Wallet Selector.", + "keywords": [ + "near", + "blockchain", + "wallets", + "dapps", + "near-protocol", + "near-blockchain", + "wallet selector", + "injected wallet", + "Rabby wallet" + ], + "repository": { + "type": "git", + "url": "https://github.com/near/wallet-selector.git" + }, + "bugs": { + "url": "https://github.com/near/wallet-selector/issues" + }, + "homepage": "https://github.com/near/wallet-selector/tree/main/packages/rabby-wallet" +} diff --git a/packages/rabby-wallet/project.json b/packages/rabby-wallet/project.json new file mode 100644 index 000000000..d63161f70 --- /dev/null +++ b/packages/rabby-wallet/project.json @@ -0,0 +1,56 @@ +{ + "name": "rabby-wallet", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/rabby-wallet/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nrwl/rollup:rollup", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/packages/rabby-wallet", + "tsConfig": "packages/rabby-wallet/tsconfig.lib.json", + "project": "packages/rabby-wallet/package.json", + "entryFile": "packages/rabby-wallet/src/index.ts", + "buildableProjectDepsInPackageJsonType": "dependencies", + "compiler": "babel", + "format": ["esm", "cjs"], + "assets": [ + { + "glob": "packages/rabby-wallet/README.md", + "input": ".", + "output": "." + }, + { + "glob": "packages/rabby-wallet/assets/*", + "input": ".", + "output": "assets" + } + ] + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["packages/rabby-wallet/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/packages/rabby-wallet"], + "options": { + "jestConfig": "packages/rabby-wallet/jest.config.ts", + "passWithNoTests": true + } + }, + "deploy": { + "executor": "ngx-deploy-npm:deploy", + "options": { + "access": "public" + }, + "dependsOn": ["^deploy"] + } + }, + "tags": ["injected-wallet"] +} diff --git a/packages/rabby-wallet/src/index.ts b/packages/rabby-wallet/src/index.ts new file mode 100644 index 000000000..da9a935b4 --- /dev/null +++ b/packages/rabby-wallet/src/index.ts @@ -0,0 +1,2 @@ +export { setupRabbyWallet } from "./lib/rabby-wallet"; +export type { RabbyWalletParams } from "./lib/rabby-wallet"; diff --git a/packages/rabby-wallet/src/lib/icon.ts b/packages/rabby-wallet/src/lib/icon.ts new file mode 100644 index 000000000..5f42ac156 --- /dev/null +++ b/packages/rabby-wallet/src/lib/icon.ts @@ -0,0 +1 @@ +export default `data:image/png;base64,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gCatf53QhtY/gGkjAQDmzJxXXdckMwwCQBkSAGDOdGa5updQ1dOtOPUPwCyQAABz1LTv/1X6/gHMCAkAMEd155VXtP4BzBIJADAntP4BtAkJADAnekEZWv8A2oIEAJiTR/fWX5fWP4BZ42JAwBzs2t7sGvW0/gHMGgkAMAcnTnMZXwDtQhcAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACIEAkAAAARIgEAACBCJAAAAESIBAAAgAiRAAAAECESAAAAIkQCAABAhEgAAACI0H8H8wE82Z4qTpgAAAAASUVORK5CYII=`; diff --git a/packages/rabby-wallet/src/lib/injected-rabby-wallet.ts b/packages/rabby-wallet/src/lib/injected-rabby-wallet.ts new file mode 100644 index 000000000..35b7270d2 --- /dev/null +++ b/packages/rabby-wallet/src/lib/injected-rabby-wallet.ts @@ -0,0 +1,73 @@ +export interface AccessKey { + publicKey: string; + secretKey: string; +} + +interface RequestSignInResponse { + accessKey: AccessKey; + accountId: string; + error: string | { type: string }; +} + +export type SignOutResponse = true | { error: string | { type: string } }; + +interface RequestSignInParams { + contractId?: string; + methodNames?: Array; +} + +interface Action { + methodName: string; + args: object; + gas: string; + deposit: string; +} + +interface SignAndSendTransactionParams { + receiverId: string; + actions: Array; +} + +export interface SignAndSendTransactionResponse { + method: string; + txHash: string; + code: number; +} + +interface Transaction { + receiverId: string; + actions: Array; +} + +interface RequestSignTransactionsParams { + transactions: Array; +} + +interface RequestSignTransactionsResponse { + txs: Array<{ + signedTx: string; + }>; +} + +export interface RabbyEvents { + signIn: () => void; + signOut: () => void; + accountChanged: (changedAccountId: string) => void; +} + +export interface InjectedRabby { + getAccountId: () => string | null; + requestSignIn: ( + params: RequestSignInParams + ) => Promise; + signOut: () => Promise; + isSignedIn: () => boolean; + on: ( + event: Event, + callback: RabbyEvents[Event] + ) => void; + signTransaction: (params: SignAndSendTransactionParams) => Promise; + requestSignTransactions: ( + params: RequestSignTransactionsParams + ) => Promise; +} diff --git a/packages/rabby-wallet/src/lib/rabby-wallet.spec.ts b/packages/rabby-wallet/src/lib/rabby-wallet.spec.ts new file mode 100644 index 000000000..03736efb1 --- /dev/null +++ b/packages/rabby-wallet/src/lib/rabby-wallet.spec.ts @@ -0,0 +1,131 @@ +/* eslint-disable @nx/enforce-module-boundaries */ +import { mock } from "jest-mock-extended"; +import type { ProviderService } from "packages/core/src/lib/services"; +import type { FinalExecutionOutcome } from "near-api-js/lib/providers"; + +import { setupRabbyWallet } from "./rabby-wallet"; +import { mockWallet } from "../../../core/src/lib/testUtils"; +import type { AccessKey, SignOutResponse } from "./injected-rabby-wallet"; +import type { InjectedWallet } from "../../../core/src/lib/wallet"; + +const accountId = "test-account.testnet"; +const transactions = [ + { + signerId: accountId, + receiverId: "test.testnet", + actions: [], + }, +]; + +jest.mock("near-api-js/lib/transaction", () => { + return { + ...jest.requireActual("near-api-js/lib/transaction"), + SignedTransaction: { + ...jest.requireActual("near-api-js/lib/transaction").SignedTransaction, + decode: jest.fn().mockReturnValue({}), + }, + }; +}); + +const mockRabby = () => { + const rabbyWallet = { + near: { + getAccountId: jest.fn().mockReturnValue(""), + requestSignIn: jest.fn(async () => { + window.rabby.near!.getAccountId = jest.fn().mockReturnValue(accountId); + + return { + accountId, + accessKey: mock(), + error: "", + }; + }), + signOut: jest.fn().mockReturnValue(mock()), + isSignedIn: jest.fn().mockReturnValue(true), + on: jest.fn(), + signTransaction: jest.fn().mockResolvedValue("signedTx"), + requestSignTransactions: jest.fn().mockResolvedValue({ + txs: [{ signedTx: "signedTx" }], + }), + }, + }; + + window.rabby = rabbyWallet; + + return window.rabby.near; +}; + +const createRabbyWallet = async () => { + const injectedRabby = mockRabby(); + const provider = mock(); + provider.sendTransaction.mockResolvedValue(mock()); + const { wallet } = await mockWallet(setupRabbyWallet(), { + provider, + }); + + return { + wallet, + injectedRabby: injectedRabby, + }; +}; + +afterEach(() => { + jest.resetModules(); +}); + +describe("signIn", () => { + it("sign into rabby wallet", async () => { + const { wallet, injectedRabby } = await createRabbyWallet(); + const accounts = await wallet.signIn({ contractId: "test.testnet" }); + expect(injectedRabby!.requestSignIn).toHaveBeenCalled(); + expect(accounts[0]?.accountId).toBe(accountId); + }); +}); + +describe("signOut", () => { + it("sign out of rabby wallet", async () => { + const { wallet, injectedRabby } = await createRabbyWallet(); + await wallet.signIn({ contractId: "test.testnet" }); + await wallet.signOut(); + + expect(injectedRabby!.signOut).toHaveBeenCalled(); + }); +}); + +describe("getAccounts", () => { + it("returns accounts", async () => { + const { wallet, injectedRabby } = await createRabbyWallet(); + await wallet.signIn({ contractId: "test.testnet" }); + const result = await wallet.getAccounts(); + + expect(injectedRabby!.getAccountId).toHaveBeenCalled(); + expect(result).toEqual([{ accountId, publicKey: undefined }]); + }); +}); + +describe("signTransaction", () => { + it("sign transaction in rabby wallet", async () => { + const { wallet, injectedRabby } = await createRabbyWallet(); + await wallet.signIn({ contractId: "test.testnet" }); + await wallet.signAndSendTransaction({ + signerId: accountId, + receiverId: "test.testnet", + actions: [], + }); + + expect(injectedRabby!.signTransaction).toHaveBeenCalled(); + }); +}); + +describe("signAndSendTransactions", () => { + it("sign transactions in rabby wallet", async () => { + const { wallet, injectedRabby } = await createRabbyWallet(); + await wallet.signIn({ contractId: "test.testnet" }); + const result = await wallet.signAndSendTransactions({ + transactions, + }); + + expect(injectedRabby!.requestSignTransactions).toHaveBeenCalled(); + expect(result.length).toEqual(transactions.length); + }); +}); diff --git a/packages/rabby-wallet/src/lib/rabby-wallet.ts b/packages/rabby-wallet/src/lib/rabby-wallet.ts new file mode 100644 index 000000000..acbec1b37 --- /dev/null +++ b/packages/rabby-wallet/src/lib/rabby-wallet.ts @@ -0,0 +1,236 @@ +import { isMobile } from "is-mobile"; +import { SignedTransaction } from "near-api-js/lib/transaction"; +import type { + Action, + FunctionCallAction, + InjectedWallet, + Optional, + Transaction, + WalletBehaviourFactory, + WalletModuleFactory, +} from "@near-wallet-selector/core"; +import { waitFor } from "@near-wallet-selector/core"; + +import icon from "./icon"; +import type { InjectedRabby } from "./injected-rabby-wallet"; + +const downloadUrl = + "https://chromewebstore.google.com/detail/rabby-wallet/acmacodkjbdgmoleebolmdjonilkdbch"; + +declare global { + interface Window { + rabby: { + near: InjectedRabby | undefined; + }; + } +} + +export interface RabbyWalletParams { + iconUrl?: string; + deprecated?: boolean; +} + +interface RabbyState { + wallet: InjectedRabby; +} + +const isInstalled = () => { + return waitFor(() => !!window.rabby?.near).catch(() => false); +}; + +const setupRabbyState = (): RabbyState => { + const wallet = window.rabby?.near!; + return { + wallet, + }; +}; + +const RabbyWallet: WalletBehaviourFactory = async ({ + metadata, + store, + emitter, + logger, + id, + provider, +}) => { + const _state = setupRabbyState(); + + const signOut = async () => { + if (!_state.wallet.isSignedIn()) { + return; + } + + await _state.wallet.signOut(); + }; + + const setupEvents = () => { + _state.wallet.on("accountChanged", async (newAccountId) => { + logger.log("onAccountChange", newAccountId); + emitter.emit("signedOut", null); + }); + }; + + const isValidActions = ( + actions: Array + ): actions is Array => { + return actions.every((x) => x.type === "FunctionCall"); + }; + + const transformActions = (actions: Array) => { + const validActions = isValidActions(actions); + + if (!validActions) { + throw new Error( + `Only 'FunctionCall' actions types are supported by ${metadata.name}` + ); + } + + return actions.map((x) => x.params); + }; + + const transformTransactions = ( + transactions: Array> + ) => { + return transactions.map((transaction) => { + return { + receiverId: transaction.receiverId, + actions: transformActions(transaction.actions), + }; + }); + }; + + if (_state.wallet && _state.wallet.isSignedIn()) { + setupEvents(); + } + + const getAccounts = async () => { + const { selectedWalletId } = store.getState(); + if (selectedWalletId === id) { + await waitFor(() => !!_state.wallet?.isSignedIn(), { + timeout: 1000, + }).catch(); + } + + const accountId = _state.wallet.getAccountId(); + + if (!accountId) { + return []; + } + + return [{ accountId }]; + }; + + const getSignedTransaction = (signedTx: string) => { + const buf = Buffer.from(signedTx, "base64"); + return SignedTransaction.decode(buf); + }; + + return { + async signIn({ contractId, methodNames }) { + try { + const { accessKey, accountId } = await _state.wallet.requestSignIn({ + contractId, + methodNames, + }); + setupEvents(); + + const publicKey = accessKey?.publicKey; + + return [ + { + accountId, + publicKey: publicKey ? publicKey.toString() : undefined, + }, + ]; + } catch (_) { + await signOut(); + throw new Error("Failed to sign in"); + } + }, + + signOut, + + getAccounts, + + async verifyOwner() { + throw new Error(`Method not supported by ${metadata.name}`); + }, + + async signMessage() { + throw new Error(`Method not supported by ${metadata.name}`); + }, + + async signAndSendTransaction({ signerId, receiverId, actions }) { + logger.log("signAndSendTransaction", { signerId, receiverId, actions }); + + const { contract } = store.getState(); + + if (!_state.wallet.isSignedIn() || !contract) { + throw new Error("Wallet not signed in"); + } + + try { + const signedTx = await _state.wallet.signTransaction({ + receiverId: receiverId || contract.contractId, + actions: transformActions(actions), + }); + const signedTransaction = getSignedTransaction(signedTx); + return provider.sendTransaction(signedTransaction); + } catch (error) { + throw new Error("sign Error"); + } + }, + + async signAndSendTransactions({ transactions }) { + logger.log("signAndSendTransactions", { transactions }); + + if (!_state.wallet.isSignedIn()) { + throw new Error("Wallet not signed in"); + } + + try { + const resp = await _state.wallet.requestSignTransactions({ + transactions: transformTransactions(transactions), + }); + + const { txs } = resp; + const results = []; + for (let i = 0; i < txs.length; i++) { + const signedTransaction = getSignedTransaction(txs[i].signedTx); + results.push(await provider.sendTransaction(signedTransaction)); + } + return results; + } catch (error) { + throw new Error("sign Error"); + } + }, + }; +}; + +export function setupRabbyWallet({ + iconUrl = icon, + deprecated = false, +}: RabbyWalletParams = {}): WalletModuleFactory { + return async () => { + const mobile = isMobile(); + if (mobile) { + return null; + } + + const installed = await isInstalled(); + + return { + id: "rabby-wallet", + type: "injected", + metadata: { + name: "Rabby Wallet", + description: "Browser extension wallet", + iconUrl, + downloadUrl, + deprecated, + available: installed, + }, + init: RabbyWallet, + }; + }; +} diff --git a/packages/rabby-wallet/tsconfig.json b/packages/rabby-wallet/tsconfig.json new file mode 100644 index 000000000..3aaed7519 --- /dev/null +++ b/packages/rabby-wallet/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "resolveJsonModule": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/rabby-wallet/tsconfig.lib.json b/packages/rabby-wallet/tsconfig.lib.json new file mode 100644 index 000000000..e85ef50f6 --- /dev/null +++ b/packages/rabby-wallet/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": [] + }, + "include": ["**/*.ts"], + "exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages/rabby-wallet/tsconfig.spec.json b/packages/rabby-wallet/tsconfig.spec.json new file mode 100644 index 000000000..b506d384e --- /dev/null +++ b/packages/rabby-wallet/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": ["jest.config.ts", "**/*.spec.ts"] +}