diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 98a27a3..cd6905d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,16 +13,16 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: '16' - registry-url: 'https://registry.npmjs.org' - cache: 'yarn' + node-version: "16" + registry-url: "https://registry.npmjs.org" + cache: "yarn" - run: yarn - run: yarn test - run: yarn lint - run: yarn build - uses: actions/upload-artifact@v2 with: - name: 'phala-js-sdk' + name: "phala-js-sdk" path: | packages/sdk/dist/ packages/sdk/package.json diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f59e096..c22fdfa 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,11 +9,11 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: '16' - registry-url: 'https://registry.npmjs.org' - cache: 'yarn' + node-version: "16" + registry-url: "https://registry.npmjs.org" + cache: "yarn" - run: yarn - run: yarn workspace @phala/sdk build - - run: yarn workspace @phala/sdk publish + - run: yarn workspace @phala/sdk auto-publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 665cc77..87785cd 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist tsconfig.tsbuildinfo .npmrc .eslintcache +browser diff --git a/.prettierrc b/.prettierrc index 653c512..27e719e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,4 @@ { - "semi": false, - "singleQuote": true, - "bracketSpacing": false + "proseWrap": "never", + "quoteProps": "consistent" } diff --git a/.vscode/settings.json b/.vscode/settings.json index a615589..a9df0ac 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,7 +4,7 @@ "source.fixAll.eslint": true, "source.sortImports": true }, - "eslint.workingDirectories": [{"pattern": "./packages/*/"}], + "eslint.workingDirectories": [{ "pattern": "./packages/*/" }], "cSpell.ignoreWords": [ "polkadot", "jotai", diff --git a/jest.config.cjs b/jest.config.cjs index b827c39..9d7be93 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -1,4 +1,4 @@ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { - preset: 'ts-jest', -} + preset: "ts-jest", +}; diff --git a/package.json b/package.json index 2c76d17..9ee7890 100644 --- a/package.json +++ b/package.json @@ -22,5 +22,8 @@ "ts-node": "^10.9.1", "typescript": "^4.8.4" }, - "packageManager": "yarn@3.2.3" + "packageManager": "yarn@3.2.3", + "dependencies": { + "@polkadot/util": "^10.2.3" + } } diff --git a/packages/example/.eslintrc b/packages/example/.eslintrc index be5724a..5f29d73 100644 --- a/packages/example/.eslintrc +++ b/packages/example/.eslintrc @@ -7,6 +7,7 @@ ], "parser": "@typescript-eslint/parser", "rules": { - "no-console": "error" + "no-console": "error", + "@typescript-eslint/no-explicit-any": 0 } } diff --git a/packages/example/atoms/account.ts b/packages/example/atoms/account.ts index c918c7b..270019e 100644 --- a/packages/example/atoms/account.ts +++ b/packages/example/atoms/account.ts @@ -1,9 +1,9 @@ -import {atomWithStorage} from 'jotai/utils' -import type {InjectedAccountWithMeta} from '@polkadot/extension-inject/types' +import { atomWithStorage } from "jotai/utils"; +import type { InjectedAccountWithMeta } from "@polkadot/extension-inject/types"; const accountAtom = atomWithStorage( - 'atom:account', + "atom:account", null -) +); -export default accountAtom +export default accountAtom; diff --git a/packages/example/components/AccountSelect.tsx b/packages/example/components/AccountSelect.tsx index 0321bf4..ab650b7 100644 --- a/packages/example/components/AccountSelect.tsx +++ b/packages/example/components/AccountSelect.tsx @@ -1,56 +1,56 @@ -import {useState, useEffect} from 'react' -import type {InjectedAccountWithMeta} from '@polkadot/extension-inject/types' -import {useAtom} from 'jotai' -import {Select} from 'baseui/select' -import {LabelSmall, MonoParagraphXSmall} from 'baseui/typography' -import {Block} from 'baseui/block' -import {FormControl} from 'baseui/form-control' -import accountAtom from '../atoms/account' -import {enablePolkadotExtension} from '../lib/polkadotExtension' +import { useState, useEffect } from "react"; +import type { InjectedAccountWithMeta } from "@polkadot/extension-inject/types"; +import { useAtom } from "jotai"; +import { Select } from "baseui/select"; +import { LabelSmall, MonoParagraphXSmall } from "baseui/typography"; +import { Block } from "baseui/block"; +import { FormControl } from "baseui/form-control"; +import accountAtom from "../atoms/account"; +import { enablePolkadotExtension } from "../lib/polkadotExtension"; const trimAddress = (address: string) => - `${address.slice(0, 6)}…${address.slice(-6)}` + `${address.slice(0, 6)}…${address.slice(-6)}`; const AccountSelect = (): JSX.Element => { - const [error, setError] = useState(false) - const [account, setAccount] = useAtom(accountAtom) - const [options, setOptions] = useState([]) + const [error, setError] = useState(false); + const [account, setAccount] = useAtom(accountAtom); + const [options, setOptions] = useState([]); useEffect(() => { - let unsubscribe: () => void + let unsubscribe: () => void; const subscribeAccounts = async () => { - await enablePolkadotExtension() + await enablePolkadotExtension(); const handleAccounts = (accounts: InjectedAccountWithMeta[]): void => { - setOptions(accounts) - } - const {web3Accounts, web3AccountsSubscribe} = await import( - '@polkadot/extension-dapp' - ) - const accounts = await web3Accounts() - handleAccounts(accounts) - unsubscribe = await web3AccountsSubscribe(handleAccounts) - } + setOptions(accounts); + }; + const { web3Accounts, web3AccountsSubscribe } = await import( + "@polkadot/extension-dapp" + ); + const accounts = await web3Accounts(); + handleAccounts(accounts); + unsubscribe = await web3AccountsSubscribe(handleAccounts); + }; try { - subscribeAccounts() + subscribeAccounts(); } catch (err) { - setError(true) - throw err + setError(true); + throw err; } - return () => unsubscribe?.() - }, []) + return () => unsubscribe?.(); + }, []); useEffect(() => { if ( account && options.length && - !options.find(({address}) => address === account.address) + !options.find(({ address }) => address === account.address) ) { - setAccount(null) + setAccount(null); } - }, [options, account, setAccount]) + }, [options, account, setAccount]); return ( @@ -63,23 +63,23 @@ const AccountSelect = (): JSX.Element => { }, }, }} - {...(error && {error: 'Polkadot{.js} extension error'})} + {...(error && { error: "Polkadot{.js} extension error" })} > - ) -} + ); +}; -export default AccountSelect +export default AccountSelect; diff --git a/packages/example/components/ContractLoader.tsx b/packages/example/components/ContractLoader.tsx index c5eb527..f449879 100644 --- a/packages/example/components/ContractLoader.tsx +++ b/packages/example/components/ContractLoader.tsx @@ -1,59 +1,59 @@ -import {create} from '@phala/sdk' -import type {ApiPromise} from '@polkadot/api' -import {ContractPromise} from '@polkadot/api-contract' -import {Button} from 'baseui/button' -import {FormControl} from 'baseui/form-control' -import {Input} from 'baseui/input' -import {Textarea} from 'baseui/textarea' -import {toaster} from 'baseui/toast' -import {useAtom} from 'jotai' -import {focusAtom} from 'jotai/optics' -import {atomWithStorage} from 'jotai/utils' -import {useRef, VFC} from 'react' -import useIsClient from '../hooks/useIsClient' -import {createApi} from '../lib/polkadotApi' +import { create } from "@phala/sdk"; +import type { ApiPromise } from "@polkadot/api"; +import { ContractPromise } from "@polkadot/api-contract"; +import { Button } from "baseui/button"; +import { FormControl } from "baseui/form-control"; +import { Input } from "baseui/input"; +import { Textarea } from "baseui/textarea"; +import { toaster } from "baseui/toast"; +import { useAtom } from "jotai"; +import { focusAtom } from "jotai/optics"; +import { atomWithStorage } from "jotai/utils"; +import { useRef, VFC } from "react"; +import useIsClient from "../hooks/useIsClient"; +import { createApi } from "../lib/polkadotApi"; const endpointAtom = atomWithStorage( - 'atom:endpoint', - 'ws://localhost:9944' -) + "atom:endpoint", + "ws://localhost:9944" +); const pruntimeURLAtom = atomWithStorage( - 'atom:pruntime_url', - 'http://localhost:8000' -) + "atom:pruntime_url", + "http://localhost:8000" +); const contractsAtom = atomWithStorage< - Record ->('atom:contracts', {}) + Record +>("atom:contracts", {}); const ContractLoader: VFC<{ - name: string - onLoad: (res: {api: ApiPromise; contract: ContractPromise}) => void -}> = ({name, onLoad}) => { + name: string; + onLoad: (res: { api: ApiPromise; contract: ContractPromise }) => void; +}> = ({ name, onLoad }) => { const contractInfoAtom = useRef( focusAtom(contractsAtom, (optic) => optic.prop(name)) - ) - const [contractInfo, setContractInfo] = useAtom(contractInfoAtom.current) - const [endpoint, setEndpoint] = useAtom(endpointAtom) - const [pruntimeURL, setPruntimeURL] = useAtom(pruntimeURLAtom) - const {contractId = '', metadata = ''} = contractInfo || {} - const isClient = useIsClient() - if (!isClient) return null + ); + const [contractInfo, setContractInfo] = useAtom(contractInfoAtom.current); + const [endpoint, setEndpoint] = useAtom(endpointAtom); + const [pruntimeURL, setPruntimeURL] = useAtom(pruntimeURLAtom); + const { contractId = "", metadata = "" } = contractInfo || {}; + const isClient = useIsClient(); + if (!isClient) return null; const loadContract = async () => { try { - const api = await createApi(endpoint) + const api = await createApi(endpoint); const contract = new ContractPromise( - (await create({api, baseURL: pruntimeURL, contractId})).api, + (await create({ api, baseURL: pruntimeURL, contractId })).api, JSON.parse(metadata), contractId - ) - onLoad({api, contract}) - toaster.positive('Contract loaded successfully', {}) + ); + onLoad({ api, contract }); + toaster.positive("Contract loaded successfully", {}); } catch (err) { - toaster.negative((err as Error).message, {}) - throw err + toaster.negative((err as Error).message, {}); + throw err; } - } + }; return ( <> @@ -63,7 +63,7 @@ const ContractLoader: VFC<{ overrides={{ Input: { style: { - fontFamily: 'monospace', + fontFamily: "monospace", }, }, }} @@ -77,7 +77,7 @@ const ContractLoader: VFC<{ overrides={{ Input: { style: { - fontFamily: 'monospace', + fontFamily: "monospace", }, }, }} @@ -90,7 +90,7 @@ const ContractLoader: VFC<{ overrides={{ Input: { style: { - fontFamily: 'monospace', + fontFamily: "monospace", }, }, }} @@ -108,8 +108,8 @@ const ContractLoader: VFC<{ overrides={{ Input: { style: { - fontFamily: 'monospace', - height: '600px', + fontFamily: "monospace", + height: "600px", }, }, }} @@ -127,7 +127,7 @@ const ContractLoader: VFC<{ Load Contract - ) -} + ); +}; -export default ContractLoader +export default ContractLoader; diff --git a/packages/example/components/Layout.tsx b/packages/example/components/Layout.tsx index 5a800fa..02d5991 100644 --- a/packages/example/components/Layout.tsx +++ b/packages/example/components/Layout.tsx @@ -1,18 +1,18 @@ -import {FC} from 'react' -import Head from 'next/head' -import {useRouter} from 'next/router' -import {HeadingXLarge} from 'baseui/typography' -import {ToasterContainer} from 'baseui/toast' -import {Block} from 'baseui/block' -import {ChevronLeft} from 'baseui/icon' -import AccountSelect from './AccountSelect' -import Link from 'next/link' -import useIsClient from '../hooks/useIsClient' +import { FC } from "react"; +import Head from "next/head"; +import { useRouter } from "next/router"; +import { HeadingXLarge } from "baseui/typography"; +import { ToasterContainer } from "baseui/toast"; +import { Block } from "baseui/block"; +import { ChevronLeft } from "baseui/icon"; +import AccountSelect from "./AccountSelect"; +import Link from "next/link"; +import useIsClient from "../hooks/useIsClient"; -const Layout: FC<{title?: string}> = ({title, children}) => { - const {pathname} = useRouter() - const isClient = useIsClient() - const displayTitle = title || 'Phala SDK Example' +const Layout: FC<{ title?: string }> = ({ title, children }) => { + const { pathname } = useRouter(); + const isClient = useIsClient(); + const displayTitle = title || "Phala SDK Example"; return ( @@ -28,14 +28,14 @@ const Layout: FC<{title?: string}> = ({title, children}) => { justifyContent="space-between" > - {pathname !== '/' && ( + {pathname !== "/" && ( = ({title, children}) => { - ) -} + ); +}; -export default Layout +export default Layout; diff --git a/packages/example/global.d.ts b/packages/example/global.d.ts index 2612ffc..8af43c0 100644 --- a/packages/example/global.d.ts +++ b/packages/example/global.d.ts @@ -1,5 +1,5 @@ -import {NextPage} from 'next' +import { NextPage } from "next"; declare global { - type Page = NextPage & {title?: string} + type Page = NextPage & { title?: string }; } diff --git a/packages/example/hooks/useInterval.ts b/packages/example/hooks/useInterval.ts index 789899b..ffa2b5f 100644 --- a/packages/example/hooks/useInterval.ts +++ b/packages/example/hooks/useInterval.ts @@ -1,25 +1,25 @@ -import {useEffect, useLayoutEffect, useRef} from 'react' +import { useEffect, useLayoutEffect, useRef } from "react"; function useInterval(callback: () => void, delay: number | null) { - const savedCallback = useRef(callback) + const savedCallback = useRef(callback); // Remember the latest callback if it changes. useLayoutEffect(() => { - savedCallback.current = callback - }, [callback]) + savedCallback.current = callback; + }, [callback]); // Set up the interval. useEffect(() => { // Don't schedule if no delay is specified. // Note: 0 is a valid value for delay. if (!delay && delay !== 0) { - return + return; } - const id = setInterval(() => savedCallback.current(), delay) + const id = setInterval(() => savedCallback.current(), delay); - return () => clearInterval(id) - }, [delay]) + return () => clearInterval(id); + }, [delay]); } -export default useInterval +export default useInterval; diff --git a/packages/example/hooks/useIsClient.ts b/packages/example/hooks/useIsClient.ts index e4cb4f7..fb4a210 100644 --- a/packages/example/hooks/useIsClient.ts +++ b/packages/example/hooks/useIsClient.ts @@ -1,12 +1,12 @@ -import {useEffect, useState} from 'react' +import { useEffect, useState } from "react"; const useIsClient = (): boolean => { - const [mounted, setMounted] = useState(false) + const [mounted, setMounted] = useState(false); useEffect(() => { - setMounted(true) - }, []) + setMounted(true); + }, []); - return mounted -} + return mounted; +}; -export default useIsClient +export default useIsClient; diff --git a/packages/example/lib/copy.ts b/packages/example/lib/copy.ts index ef6e117..08a6771 100644 --- a/packages/example/lib/copy.ts +++ b/packages/example/lib/copy.ts @@ -1,7 +1,7 @@ -import {toaster} from 'baseui/toast' +import { toaster } from "baseui/toast"; export const copy = async (text: string) => { - await navigator.clipboard.writeText(text) + await navigator.clipboard.writeText(text); - toaster.positive('Copied to Clipboard', {}) -} + toaster.positive("Copied to Clipboard", {}); +}; diff --git a/packages/example/lib/polkadotApi.ts b/packages/example/lib/polkadotApi.ts index e375c50..cc0e5cc 100644 --- a/packages/example/lib/polkadotApi.ts +++ b/packages/example/lib/polkadotApi.ts @@ -1,9 +1,9 @@ -import {khalaDev} from '@phala/typedefs' -import {ApiPromise, WsProvider} from '@polkadot/api' -import {types as phalaSDKTypes} from '@phala/sdk' +import { khalaDev } from "@phala/typedefs"; +import { ApiPromise, WsProvider } from "@polkadot/api"; +import { types as phalaSDKTypes } from "@phala/sdk"; export const createApi = async (endpoint: string): Promise => { - const wsProvider = new WsProvider(endpoint) + const wsProvider = new WsProvider(endpoint); const api = await ApiPromise.create({ provider: wsProvider, @@ -11,7 +11,7 @@ export const createApi = async (endpoint: string): Promise => { ...khalaDev, ...phalaSDKTypes, }, - }) + }); - return api -} + return api; +}; diff --git a/packages/example/lib/polkadotExtension.ts b/packages/example/lib/polkadotExtension.ts index 2217956..3a4026e 100644 --- a/packages/example/lib/polkadotExtension.ts +++ b/packages/example/lib/polkadotExtension.ts @@ -1,31 +1,31 @@ -import type {InjectedAccountWithMeta} from '@polkadot/extension-inject/types' -import {Signer} from '@polkadot/types/types' +import type { InjectedAccountWithMeta } from "@polkadot/extension-inject/types"; +import { Signer } from "@polkadot/types/types"; -let enablePolkadotExtensionCache: Promise +let enablePolkadotExtensionCache: Promise; export const enablePolkadotExtension = async (): Promise => { - if (enablePolkadotExtensionCache) return enablePolkadotExtensionCache + if (enablePolkadotExtensionCache) return enablePolkadotExtensionCache; enablePolkadotExtensionCache = (async () => { - const {web3Enable} = await import('@polkadot/extension-dapp') - const extensions = await web3Enable('Phala SDK Example') + const { web3Enable } = await import("@polkadot/extension-dapp"); + const extensions = await web3Enable("Phala SDK Example"); if (extensions.length === 0) { throw new Error( - 'No extension installed, or the user did not accept the authorization' - ) + "No extension installed, or the user did not accept the authorization" + ); } - })() + })(); - return enablePolkadotExtensionCache -} + return enablePolkadotExtensionCache; +}; export const getSigner = async ( account: InjectedAccountWithMeta ): Promise => { - await enablePolkadotExtension() - const {web3FromSource} = await import('@polkadot/extension-dapp') - const injector = await web3FromSource(account.meta.source) - const signer = injector.signer + await enablePolkadotExtension(); + const { web3FromSource } = await import("@polkadot/extension-dapp"); + const injector = await web3FromSource(account.meta.source); + const signer = injector.signer; - return signer -} + return signer; +}; diff --git a/packages/example/next.config.mjs b/packages/example/next.config.mjs index d54ff92..1222e3b 100644 --- a/packages/example/next.config.mjs +++ b/packages/example/next.config.mjs @@ -2,10 +2,10 @@ const nextConfig = { reactStrictMode: true, webpack: function (config) { - config.externals = config.externals || {} - config.externals['styletron-server'] = 'styletron-server' - return config + config.externals = config.externals || {}; + config.externals["styletron-server"] = "styletron-server"; + return config; }, -} +}; -export default nextConfig +export default nextConfig; diff --git a/packages/example/pages/_app.tsx b/packages/example/pages/_app.tsx index 3ecdbe1..8ffe075 100644 --- a/packages/example/pages/_app.tsx +++ b/packages/example/pages/_app.tsx @@ -1,11 +1,11 @@ -import '../styles/globals.css' -import type {AppProps} from 'next/app' -import {Provider as StyletronProvider} from 'styletron-react' -import {LightTheme, BaseProvider} from 'baseui' -import Layout from '../components/Layout' -import {styletron} from '../styletron' +import "../styles/globals.css"; +import type { AppProps } from "next/app"; +import { Provider as StyletronProvider } from "styletron-react"; +import { LightTheme, BaseProvider } from "baseui"; +import Layout from "../components/Layout"; +import { styletron } from "../styletron"; -function MyApp({Component, pageProps}: AppProps & {Component: Page}) { +function MyApp({ Component, pageProps }: AppProps & { Component: Page }) { return ( @@ -14,6 +14,6 @@ function MyApp({Component, pageProps}: AppProps & {Component: Page}) { - ) + ); } -export default MyApp +export default MyApp; diff --git a/packages/example/pages/_document.tsx b/packages/example/pages/_document.tsx index d325779..857c51a 100644 --- a/packages/example/pages/_document.tsx +++ b/packages/example/pages/_document.tsx @@ -4,13 +4,13 @@ import Document, { Html, Main, NextScript, -} from 'next/document' -import {Server} from 'styletron-engine-atomic' -import {Provider as StyletronProvider} from 'styletron-react' -import {styletron} from '../styletron' +} from "next/document"; +import { Server } from "styletron-engine-atomic"; +import { Provider as StyletronProvider } from "styletron-react"; +import { styletron } from "../styletron"; // https://github.com/vercel/next.js/blob/canary/examples/with-styletron/pages/_document.js -class MyDocument extends Document<{stylesheets: any[]}> { +class MyDocument extends Document<{ stylesheets: any[] }> { static async getInitialProps(ctx: DocumentContext) { const renderPage = () => ctx.renderPage({ @@ -21,13 +21,13 @@ class MyDocument extends Document<{stylesheets: any[]}> { ), - }) + }); const initialProps = await Document.getInitialProps({ ...ctx, renderPage, - }) - const stylesheets = (styletron as Server).getStylesheets() || [] - return {...initialProps, stylesheets} + }); + const stylesheets = (styletron as Server).getStylesheets() || []; + return { ...initialProps, stylesheets }; } render() { @@ -37,9 +37,9 @@ class MyDocument extends Document<{stylesheets: any[]}> { {this.props.stylesheets.map((sheet, i) => (