├── packages ├── auth-kit │ ├── example │ │ ├── .env.sample │ │ ├── src │ │ │ ├── vite-env.d.ts │ │ │ ├── index.css │ │ │ ├── main.tsx │ │ │ ├── AppBar.tsx │ │ │ └── App.tsx │ │ ├── tsconfig.node.json │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.html │ │ ├── tsconfig.json │ │ ├── vite.config.ts │ │ ├── package.json │ │ └── public │ │ │ └── vite.svg │ ├── src │ │ ├── index.ts │ │ ├── types.ts │ │ ├── adapters │ │ │ └── Web3AuthAdapter.ts │ │ └── SafeAuthKit.ts │ ├── tsconfig.json │ ├── README.md │ └── package.json ├── onramp-kit │ ├── example │ │ ├── client │ │ │ ├── src │ │ │ │ ├── vite-env.d.ts │ │ │ │ ├── index.css │ │ │ │ ├── main.tsx │ │ │ │ ├── AppBar.tsx │ │ │ │ └── App.tsx │ │ │ ├── .env.sample │ │ │ ├── tsconfig.node.json │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── tsconfig.json │ │ │ ├── vite.config.ts │ │ │ ├── package.json │ │ │ └── public │ │ │ │ └── vite.svg │ │ └── server │ │ │ ├── src │ │ │ ├── router │ │ │ │ ├── router.ts │ │ │ │ └── stripe-router.ts │ │ │ ├── lib │ │ │ │ └── logger │ │ │ │ │ └── logger.ts │ │ │ ├── server.ts │ │ │ ├── controllers │ │ │ │ └── stripe-controller.ts │ │ │ └── services │ │ │ │ └── stripe-service.ts │ │ │ ├── README.md │ │ │ ├── example.env │ │ │ ├── index.ts │ │ │ ├── .gitignore │ │ │ ├── package.json │ │ │ ├── tsconfig.json │ │ │ └── yarn.lock │ ├── src │ │ ├── types │ │ │ ├── declarations.d.ts │ │ │ ├── index.ts │ │ │ ├── events.ts │ │ │ ├── onRamp.ts │ │ │ └── stripe.ts │ │ ├── index.ts │ │ ├── adapters │ │ │ └── stripe │ │ │ │ ├── stripeApi.ts │ │ │ │ ├── utils.ts │ │ │ │ └── StripeAdapter.ts │ │ └── SafeOnRampKit.ts │ ├── tsconfig.json │ ├── package.json │ └── README.md ├── relay-kit │ ├── src │ │ ├── index.ts │ │ ├── constants.ts │ │ ├── types.ts │ │ └── GelatoRelayAdapter.ts │ ├── tsconfig.json │ ├── README.md │ └── package.json └── account-abstraction-kit │ ├── src │ ├── utils │ │ ├── index.ts │ │ ├── signatures.ts │ │ ├── deployments.ts │ │ └── contracts.ts │ ├── index.ts │ ├── constants │ │ └── index.ts │ ├── types │ │ └── index.ts │ └── AccountAbstraction.ts │ ├── tsconfig.json │ ├── scripts │ └── typechain.ts │ ├── README.md │ └── package.json ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ ├── lint.yml │ ├── test.yml │ └── cla.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── .prettierrc.json ├── lerna.json ├── tsconfig.json ├── .eslintrc.js ├── playground ├── config │ └── run.ts └── relay-kit │ ├── sponsored-transaction.ts │ └── paid-transaction.ts ├── .gitignore ├── LICENSE.md ├── package.json ├── tsconfig.settings.json └── README.md /packages/auth-kit/example/.env.sample: -------------------------------------------------------------------------------- 1 | VITE_WEB3AUTH_CLIENT_ID= 2 | VITE_INFURA_KEY= -------------------------------------------------------------------------------- /packages/auth-kit/example/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/relay-kit/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GelatoRelayAdapter' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## What it solves 2 | 3 | Resolves # 4 | 5 | ## How this PR fixes it 6 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/types/declarations.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line 2 | declare var StripeOnramp: any 3 | -------------------------------------------------------------------------------- /packages/auth-kit/example/src/index.css: -------------------------------------------------------------------------------- 1 | @import url('../node_modules/@safe-global/safe-react-components/dist/fonts.css'); 2 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './events' 2 | export * from './onRamp' 3 | export * from './stripe' 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "semi": false, 4 | "singleQuote": true, 5 | "trailingComma": "none" 6 | } 7 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/.env.sample: -------------------------------------------------------------------------------- 1 | VITE_STRIPE_PUBLIC_KEY= 2 | VITE_SAFE_STRIPE_BACKEND_BASE_URL= 3 | VITE_SESSION_ADDRESS= -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/src/index.css: -------------------------------------------------------------------------------- 1 | @import url('../node_modules/@safe-global/safe-react-components/dist/fonts.css'); 2 | -------------------------------------------------------------------------------- /packages/auth-kit/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types' 2 | 3 | import SafeAuthKit from './SafeAuthKit' 4 | 5 | export { SafeAuthKit } 6 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './contracts' 2 | export * from './deployments' 3 | export * from './signatures' 4 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types' 2 | 3 | import { SafeOnRampKit } from './SafeOnRampKit' 4 | 5 | export { SafeOnRampKit } 6 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/index.ts: -------------------------------------------------------------------------------- 1 | import AccountAbstraction from './AccountAbstraction' 2 | 3 | export default AccountAbstraction 4 | export * from './types' 5 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/src/router/router.ts: -------------------------------------------------------------------------------- 1 | import stripeRouter from '../router/stripe-router' 2 | 3 | const routes = [stripeRouter] 4 | 5 | export default routes 6 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "independent", 6 | "useWorkspaces": true, 7 | "command": { 8 | "run": { 9 | "npmClient": "yarn" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/auth-kit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.settings.json", 3 | "compilerOptions": { 4 | "composite": true, 5 | "outDir": "dist", 6 | "baseUrl": "src" 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/onramp-kit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.settings.json", 3 | "compilerOptions": { 4 | "composite": true, 5 | "outDir": "dist", 6 | "baseUrl": "src" 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/relay-kit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.settings.json", 3 | "compilerOptions": { 4 | "composite": true, 5 | "outDir": "dist", 6 | "baseUrl": "src" 7 | }, 8 | "include": ["src", "src/**/*.json"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.settings.json", 3 | "compilerOptions": { 4 | "composite": true, 5 | "outDir": "dist", 6 | "baseUrl": "src" 7 | }, 8 | "include": ["src", "typechain"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/auth-kit/example/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "packages/account-abstraction-kit" }, 5 | { "path": "packages/relay-kit" }, 6 | { "path": "packages/auth-kit" }, 7 | { "path": "packages/onramp-kit" } 8 | ], 9 | "include": ["contracts/abis/**/*.json"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/README.md: -------------------------------------------------------------------------------- 1 | # How to use 2 | 3 | ### create a .env file 4 | 5 | ``` 6 | FRONTEND_ORGIN=http://localhost:3000,http://127.0.0.1:5173 7 | SERVER_PORT=3001 8 | STRIPE_SERVER_SECRET_KEY= 9 | ``` 10 | 11 | ### run server 12 | 13 | ```bash 14 | yarn install 15 | yarn start 16 | ``` -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/example.env: -------------------------------------------------------------------------------- 1 | 2 | # Frontend origin (CORS) 3 | FRONTEND_ORGIN=http://localhost:3000,http://127.0.0.1:5173 4 | 5 | # Server port 6 | SERVER_PORT=3001 7 | 8 | # Stripe merchant Id see: https://paper.dropbox.com/doc/Public-Crypto-Onramp-Pilot-API-Testing-Guide-csKFlmSELSKNvuc1xenRd 9 | STRIPE_SERVER_SECRET_KEY= 10 | -------------------------------------------------------------------------------- /packages/relay-kit/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const GELATO_NATIVE_TOKEN_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' 2 | 3 | export const GELATO_FEE_COLLECTOR = '0x3AC05161b76a35c1c28dC99Aa01BEd7B24cEA3bf' 4 | 5 | export const GELATO_RELAY_URL = 'https://relay.gelato.digital' 6 | 7 | export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' 8 | -------------------------------------------------------------------------------- /packages/auth-kit/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/README.md: -------------------------------------------------------------------------------- 1 | # How to use 2 | 3 | This is an example of how to use the `@safe-global/onramp-kit` package. 4 | 5 | ```bash 6 | yarn install 7 | yarn start 8 | ``` 9 | 10 | This example can be used as a playground to test the package as it is relatively imported from the root of the project. 11 | 12 | ```typescript 13 | import { SafeOnRampKit, SafeOnRampProviderType } from '../../src/index' 14 | ``` 15 | -------------------------------------------------------------------------------- /packages/auth-kit/example/README.md: -------------------------------------------------------------------------------- 1 | # How to use 2 | 3 | This is an example of how to use the `@safe-global/auth-kit` package. 4 | 5 | ```bash 6 | yarn install 7 | yarn start 8 | ``` 9 | 10 | This example can be used as a playground to test the package as it is relatively imported from the root of the project. 11 | 12 | ```typescript 13 | import { SafeAuthKit, SafeAuthProviderType, SafeAuthSignInData } from '../../src/index' 14 | ``` 15 | -------------------------------------------------------------------------------- /packages/auth-kit/example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Auth Provider demo 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: 'ESLint check' 2 | on: [pull_request] 3 | 4 | jobs: 5 | eslint: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v3 9 | 10 | - uses: actions/setup-node@v3 11 | with: 12 | node-version: 18 13 | cache: yarn 14 | 15 | - name: Install Dependencies 16 | run: yarn install --frozen-lockfile 17 | 18 | - name: Run eslint 19 | run: yarn lint:check -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Payments Provider demo 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/src/lib/logger/logger.ts: -------------------------------------------------------------------------------- 1 | import pinoHttp from 'pino-http' 2 | 3 | const logger = pinoHttp({ 4 | serializers: { 5 | req(req) { 6 | req.body = req.raw.body // log the body request 7 | return req 8 | } 9 | }, 10 | 11 | // Override attribute keys for the log object 12 | customAttributeKeys: { 13 | req: 'request', 14 | res: 'response' 15 | } 16 | }) 17 | 18 | export default logger 19 | 20 | export const log = logger.logger 21 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/index.ts: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv' 2 | 3 | import Server from './src/server' 4 | import routes from './src/router/router' 5 | 6 | dotenv.config() 7 | 8 | const { SERVER_PORT, FRONTEND_ORGIN } = process.env 9 | 10 | const allowedOrigins = FRONTEND_ORGIN?.split(',') 11 | 12 | const DEFAULT_SERVER_PORT = '3001' 13 | 14 | const server = new Server() 15 | 16 | server.configureCors(allowedOrigins) 17 | 18 | server.registerRoutes(routes) 19 | 20 | server.start(SERVER_PORT || DEFAULT_SERVER_PORT) 21 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # environment variables 4 | .env 5 | 6 | # dependencies 7 | node_modules 8 | /.pnp 9 | .pnp.js 10 | 11 | # testing 12 | coverage 13 | coverage.json 14 | 15 | # production 16 | build 17 | 18 | # misc 19 | .DS_Store 20 | .env.local 21 | .env.development.local 22 | .env.test.local 23 | .env.production.local 24 | 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | 29 | typechain 30 | typechain-types 31 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/adapters/stripe/stripeApi.ts: -------------------------------------------------------------------------------- 1 | export const createSession = ( 2 | baseUrl: string, 3 | { walletAddress, networks }: { walletAddress: string; networks: string[] } 4 | ) => { 5 | return fetch(`${baseUrl}/api/v1/onramp/stripe/session`, { 6 | method: 'POST', 7 | headers: { 8 | 'Content-Type': 'application/json' 9 | }, 10 | body: JSON.stringify({ walletAddress, networks }) 11 | }) 12 | } 13 | 14 | export const getSession = (baseUrl: string, sessionId: string) => { 15 | return fetch(`${baseUrl}/api/v1/onramp/stripe/session/${sessionId}`) 16 | } 17 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/src/router/stripe-router.ts: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | 3 | import stripeController from '../controllers/stripe-controller' 4 | 5 | const STRIPE_CREATE_SESSION_PATHNAME = '/api/v1/onramp/stripe/session' 6 | const STRIPE_GET_SESSION_PATHNAME = '/api/v1/onramp/stripe/session/:sessionId' 7 | 8 | const stripeRouter = express.Router() 9 | 10 | stripeRouter.post(STRIPE_CREATE_SESSION_PATHNAME, stripeController.getStripeClientSecret) 11 | stripeRouter.get(STRIPE_GET_SESSION_PATHNAME, stripeController.getStripeSession) 12 | 13 | export default stripeRouter 14 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/src/main.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import { SafeThemeProvider } from '@safe-global/safe-react-components' 3 | import { ThemeProvider, CssBaseline } from '@mui/material' 4 | 5 | import App from './App' 6 | 7 | import './index.css' 8 | 9 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 10 | 11 | {(safeTheme) => ( 12 | 13 | 14 | 15 | 16 | )} 17 | 18 | ) 19 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser 3 | extends: [ 4 | 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin 5 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 6 | ], 7 | parserOptions: { 8 | ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features 9 | sourceType: 'module', // Allows for the use of imports 10 | }, 11 | } -------------------------------------------------------------------------------- /playground/config/run.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process' 2 | 3 | const playInput = process.argv[2] 4 | 5 | const playgroundPaths = { 6 | 'paid-transaction': 'relay-kit/paid-transaction', 7 | 'sponsored-transaction': 'relay-kit/sponsored-transaction' 8 | } 9 | 10 | const path = playgroundPaths[playInput] 11 | if (!path) { 12 | console.log('Execute one of the existing playgrounds:') 13 | const playgrounds = Object.keys(playgroundPaths) 14 | playgrounds.forEach((playground) => { 15 | console.log(` > yarn play ${playground}`) 16 | }) 17 | process.exit() 18 | } 19 | 20 | execSync(`ts-node ./playground/${path}`, { stdio: 'inherit' }) 21 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/types/events.ts: -------------------------------------------------------------------------------- 1 | type eventCallback = (eventData: SafeOnRampEvent) => void 2 | 3 | export interface SafeOnRampEventHandlers { 4 | onLoaded?: () => void 5 | onPaymentSuccessful?: eventCallback 6 | onPaymentError?: eventCallback 7 | onPaymentProcessing?: eventCallback 8 | } 9 | 10 | export interface SafeOnRampEvent { 11 | txId: string 12 | walletAddress: string 13 | totalFee: string 14 | totalAmount: string 15 | destination: { 16 | asset?: string 17 | amount: string | null 18 | network?: string 19 | } 20 | source: { 21 | asset?: string 22 | amount: string | null 23 | network?: string 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/auth-kit/example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /packages/auth-kit/example/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import { SafeThemeProvider } from '@safe-global/safe-react-components' 4 | import { ThemeProvider, CssBaseline } from '@mui/material' 5 | 6 | import App from './App' 7 | 8 | import './index.css' 9 | 10 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 11 | 12 | 13 | {(safeTheme) => ( 14 | 15 | 16 | 17 | 18 | )} 19 | 20 | 21 | ) 22 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/types/onRamp.ts: -------------------------------------------------------------------------------- 1 | import { SafeOnRampEventHandlers } from './events' 2 | import { StripeProviderConfig } from './stripe' 3 | 4 | export interface SafeOnRampClient { 5 | init(): Promise 6 | open(options: SafeOnRampOpenOptions): Promise 7 | close(): Promise 8 | } 9 | 10 | type Network = 'ethereum' | 'polygon' 11 | 12 | export interface SafeOnRampOpenOptions { 13 | element: HTMLElement | string 14 | walletAddress: string 15 | networks: Network[] 16 | events?: SafeOnRampEventHandlers 17 | sessionId?: string 18 | } 19 | 20 | export enum SafeOnRampProviderType { 21 | Stripe 22 | } 23 | 24 | export interface SafeOnRampConfig { 25 | onRampProviderConfig: StripeProviderConfig // Add other providers here when adapters are created 26 | } 27 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/scripts/typechain.ts: -------------------------------------------------------------------------------- 1 | import { glob, runTypeChain } from 'typechain' 2 | 3 | const safeContractsRoute = '../../node_modules/@gnosis.pm/safe-contracts/build/artifacts/contracts' 4 | 5 | async function main() { 6 | const cwd = process.cwd() 7 | // find all files matching the glob 8 | const allFiles = glob(cwd, [ 9 | `${safeContractsRoute}/GnosisSafe.sol/GnosisSafe.json`, 10 | `${safeContractsRoute}/proxies/GnosisSafeProxyFactory.sol/GnosisSafeProxyFactory.json`, 11 | `${safeContractsRoute}/libraries/MultiSendCallOnly.sol/MultiSendCallOnly.json` 12 | ]) 13 | const result = await runTypeChain({ 14 | cwd, 15 | filesToProcess: allFiles, 16 | allFiles, 17 | outDir: 'typechain', 18 | target: 'ethers-v5' 19 | }) 20 | } 21 | 22 | main().catch(console.error) 23 | -------------------------------------------------------------------------------- /packages/auth-kit/example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill' 4 | import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill' 5 | 6 | export default defineConfig({ 7 | plugins: [react()], 8 | server: { 9 | port: 3000 10 | }, 11 | optimizeDeps: { 12 | disabled: false, 13 | esbuildOptions: { 14 | define: { 15 | global: 'globalThis' 16 | }, 17 | plugins: [ 18 | NodeGlobalsPolyfillPlugin({ 19 | buffer: true, 20 | process: true 21 | }), 22 | NodeModulesPolyfillPlugin() 23 | ] 24 | } 25 | }, 26 | define: { 27 | 'process.env': {}, 28 | global: {} 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/src/AppBar.tsx: -------------------------------------------------------------------------------- 1 | import { AppBar as MuiAppBar, Typography, styled } from '@mui/material' 2 | 3 | const AppBar = () => { 4 | return ( 5 | 6 | 7 | Payments Provider Demo 8 | 9 | 10 | ) 11 | } 12 | 13 | const StyledAppBar = styled(MuiAppBar)` 14 | && { 15 | position: sticky; 16 | top: 0; 17 | background: ${({ theme }) => theme.palette.background.paper}; 18 | height: 70px; 19 | align-items: center; 20 | justify-content: space-between; 21 | flex-direction: row; 22 | border-bottom: 2px solid ${({ theme }) => theme.palette.background.paper}; 23 | box-shadow: none; 24 | } 25 | ` 26 | 27 | export default AppBar 28 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill' 4 | import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill' 5 | 6 | export default defineConfig({ 7 | plugins: [react()], 8 | server: { 9 | port: 3000 10 | }, 11 | optimizeDeps: { 12 | disabled: false, 13 | esbuildOptions: { 14 | define: { 15 | global: 'globalThis' 16 | }, 17 | plugins: [ 18 | NodeGlobalsPolyfillPlugin({ 19 | buffer: true, 20 | process: true 21 | }), 22 | NodeModulesPolyfillPlugin() 23 | ] 24 | } 25 | }, 26 | define: { 27 | 'process.env': {}, 28 | global: {} 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/adapters/stripe/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility function to load a script and inject it into the DOM 3 | * @param url The url of the script to load 4 | * @param async If the script should be loaded asynchronously 5 | * @param type The type of the script 6 | */ 7 | export const loadScript = ( 8 | url: string, 9 | async = 'true', 10 | type = 'text/javascript' 11 | ): Promise => { 12 | return new Promise((resolve, reject) => { 13 | const scriptElement = document.createElement('script') 14 | 15 | scriptElement.setAttribute('src', url) 16 | scriptElement.setAttribute('type', type) 17 | scriptElement.setAttribute('async', async) 18 | 19 | document.body.appendChild(scriptElement) 20 | 21 | scriptElement.addEventListener('load', () => { 22 | resolve() 23 | }) 24 | 25 | scriptElement.addEventListener('error', () => { 26 | reject() 27 | }) 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /packages/auth-kit/src/types.ts: -------------------------------------------------------------------------------- 1 | import { ExternalProvider } from '@ethersproject/providers' 2 | 3 | export interface SafeAuthSignInData { 4 | chainId: string 5 | eoa: string 6 | safes?: string[] 7 | } 8 | 9 | export interface SafeAuthClient { 10 | provider: ExternalProvider | null 11 | init(): Promise 12 | signIn(): Promise 13 | signOut(): Promise 14 | } 15 | 16 | export enum SafeAuthProviderType { 17 | Web3Auth 18 | } 19 | 20 | export interface Web3AuthProviderConfig { 21 | rpcTarget: string 22 | clientId: string 23 | network: 'mainnet' | 'aqua' | 'celeste' | 'cyan' | 'testnet' 24 | theme: 'light' | 'dark' | 'auto' 25 | appLogo?: string 26 | } 27 | 28 | export interface SafeAuthConfig { 29 | chainId: string 30 | txServiceUrl?: string 31 | authProviderConfig: Web3AuthProviderConfig 32 | } 33 | 34 | export const SafeAuthEvents = { 35 | SIGNED_IN: 'SIGNED_IN', 36 | SIGNED_OUT: 'SIGNED_OUT' 37 | } 38 | -------------------------------------------------------------------------------- /packages/relay-kit/src/types.ts: -------------------------------------------------------------------------------- 1 | import { RelayResponse, TransactionStatusResponse } from '@gelatonetwork/relay-sdk' 2 | import { BigNumber } from 'ethers' 3 | 4 | // TO-DO: Duplicated. Remove local type and import from "types" package 5 | // { 6 | 7 | export interface MetaTransactionOptions { 8 | gasLimit: BigNumber 9 | gasToken?: string 10 | isSponsored?: boolean 11 | } 12 | 13 | export interface RelayAdapter { 14 | getFeeCollector(): string 15 | getEstimateFee(chainId: number, gasLimit: BigNumber, gasToken?: string): Promise 16 | getTaskStatus(taskId: string): Promise 17 | relayTransaction(transaction: RelayTransaction): Promise 18 | } 19 | 20 | export interface RelayTransaction { 21 | target: string 22 | encodedTransaction: string 23 | chainId: number 24 | options: MetaTransactionOptions 25 | } 26 | 27 | // } 28 | // TO-DO: Duplicated. Remove local type and import from "types" package 29 | -------------------------------------------------------------------------------- /packages/auth-kit/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@safe-global/auth-kit-example", 3 | "private": true, 4 | "version": "0.1.0", 5 | "type": "module", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11.10.5", 13 | "@emotion/styled": "^11.10.5", 14 | "@mui/material": "^5.11.7", 15 | "@safe-global/safe-react-components": "^2.0.1", 16 | "ethers": "^6.0.3", 17 | "react": "^18.2.0", 18 | "react-dom": "^18.2.0" 19 | }, 20 | "devDependencies": { 21 | "@esbuild-plugins/node-globals-polyfill": "^0.2.3", 22 | "@esbuild-plugins/node-modules-polyfill": "^0.2.2", 23 | "@rollup/plugin-commonjs": "^24.0.1", 24 | "@types/react": "^18.0.27", 25 | "@types/react-dom": "^18.0.10", 26 | "@vitejs/plugin-react": "^3.1.0", 27 | "rollup-plugin-polyfill-node": "^0.12.0", 28 | "typescript": "^4.9.3", 29 | "vite": "^4.1.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/relay-kit/README.md: -------------------------------------------------------------------------------- 1 | # Relay Kit 2 | 3 | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Frelay-kit.svg)](https://badge.fury.io/js/%40safe-global%2Frelay-kit) 4 | [![GitHub Release](https://img.shields.io/github/release/safe-global/account-abstraction-sdk.svg?style=flat)](https://github.com/safe-global/account-abstraction-sdk/releases) 5 | [![GitHub](https://img.shields.io/github/license/safe-global/account-abstraction-sdk)](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md) 6 | 7 | The Relay Kit allows to abstract users from the transaction fees payment (gas fees) allowing the use of native token or ERC-20 tokens. This will enable you to pay transaction fees directly from funding available in a Safe. 8 | 9 | ## Reference 10 | 11 | - [Relay Kit docs](https://docs.safe.global/learn/safe-core-account-abstraction-sdk/relay-kit) 12 | 13 | 14 | ## License 15 | 16 | This library is [released under MIT](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md). -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@safe-global/onramp-kit-example-client", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11.10.5", 13 | "@emotion/styled": "^11.10.5", 14 | "@mui/material": "^5.11.7", 15 | "@safe-global/safe-react-components": "^2.0.1", 16 | "ethers": "^6.0.3", 17 | "react": "^18.2.0", 18 | "react-dom": "^18.2.0" 19 | }, 20 | "devDependencies": { 21 | "@esbuild-plugins/node-globals-polyfill": "^0.2.3", 22 | "@esbuild-plugins/node-modules-polyfill": "^0.2.2", 23 | "@rollup/plugin-commonjs": "^24.0.1", 24 | "@types/react": "^18.0.27", 25 | "@types/react-dom": "^18.0.10", 26 | "@vitejs/plugin-react": "^3.1.0", 27 | "rollup-plugin-polyfill-node": "^0.12.0", 28 | "typescript": "^4.9.3", 29 | "vite": "^4.1.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | yarn-debug.log* 5 | yarn-error.log* 6 | 7 | # Diagnostic reports (https://nodejs.org/api/report.html) 8 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | *.lcov 13 | 14 | # nyc test coverage 15 | .nyc_output 16 | 17 | # Compiled binary addons 18 | build/ 19 | dist/ 20 | 21 | # Dependency directories 22 | node_modules/ 23 | 24 | # Optional npm cache directory 25 | .npm 26 | 27 | # Optional eslint cache 28 | .eslintcache 29 | 30 | # Yarn Integrity file 31 | .yarn-integrity 32 | 33 | # dotenv environment variables file 34 | .env 35 | .env.test 36 | .env.local 37 | 38 | # Stores VSCode versions used for testing VSCode extensions 39 | .vscode 40 | .vscode-test 41 | 42 | # yarn v2 43 | .yarn/cache 44 | .yarn/unplugged 45 | .yarn/build-state.yml 46 | .yarn/install-state.gz 47 | .pnp.* 48 | 49 | # macOS 50 | .DS_Store 51 | 52 | # Hardhat files 53 | cache 54 | artifacts 55 | deployments 56 | 57 | # Typechain 58 | typechain 59 | 60 | openapi/ 61 | 62 | .idea 63 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea or feature request for the Safe Account Abstraction SDK 4 | --- 5 | 6 | ## Prerequisites 7 | 8 | - First, many thanks for taking part in the community and helping us improve. We appreciate that a lot. 9 | - Support questions are better asked in our Discord chat: https://chat.safe.global/ 10 | - Please ensure the issue isn't already reported. 11 | 12 | _Please delete the above section and the instructions in the sections below before submitting_ 13 | 14 | ## Context / issue 15 | 16 | Why is this feature needed? 17 | 18 | In case your feature request related to a problem, please add clear and concise description of what the issue is. 19 | 20 | ## Proposed solution 21 | 22 | Please add a clear and concise description of what you want to happen. 23 | 24 | ## Alternatives 25 | 26 | Please add a clear and concise description of any alternative solutions or features you have considered. 27 | 28 | ## Additional context 29 | 30 | Add any other context about the feature request here. 31 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@safe-global/onramp-kit-example-client", 3 | "version": "0.1.0", 4 | "description": "Account abstraction basic Stripe service", 5 | "main": "index.ts", 6 | "license": "MIT", 7 | "author": "Daniel Somoza", 8 | "private": true, 9 | "scripts": { 10 | "build": "tsc", 11 | "prestart:prod": "yarn build", 12 | "start:prod": "node build/index.js | pino-pretty", 13 | "start": "nodemon --exec ts-node index.ts | pino-pretty", 14 | "test": "echo 'add tests'", 15 | "test:coverage": "echo 'add tests'" 16 | }, 17 | "dependencies": { 18 | "axios": "^1.3.3", 19 | "cors": "^2.8.5", 20 | "dotenv": "^16.0.3", 21 | "express": "^4.18.2", 22 | "pine": "^1.1.1", 23 | "pino-http": "^8.3.3", 24 | "pino-pretty": "^9.2.0" 25 | }, 26 | "devDependencies": { 27 | "@types/cors": "^2.8.13", 28 | "@types/express": "^4.17.17", 29 | "@types/node": "^18.13.0", 30 | "nodemon": "^2.0.20", 31 | "ts-node": "^10.9.1", 32 | "typescript": "^4.9.5" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Monorepo Test 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | - development 8 | env: 9 | INFURA_KEY: ${{ secrets.INFURA_KEY }} 10 | jobs: 11 | test: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | node-version: [16.x] 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | 23 | - name: Yarn cache 24 | uses: actions/cache@v2 25 | with: 26 | path: '**/node_modules' 27 | key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} 28 | 29 | - name: Yarn install 30 | run: | 31 | mkdir .yarncache 32 | yarn install --cache-folder ./.yarncache --frozen-lockfile 33 | rm -rf .yarncache 34 | yarn cache clean 35 | 36 | - name: Build 37 | run: yarn build 38 | 39 | - name: Test 40 | run: yarn test 41 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' 2 | 3 | // keccak256(toUtf8Bytes('Safe Account Abstraction')) 4 | export const PREDETERMINED_SALT_NONCE = 5 | '0xb1073742015cbcf5a3a4d9d1ae33ecf619439710b89475f92e2abd2117e90f90' 6 | 7 | export const SIGNED_TYPE_DATA_METHOD = 'eth_signTypedData_v4' 8 | 9 | export const EIP712_SAFE_TX_TYPES = { 10 | EIP712Domain: [ 11 | { 12 | type: 'uint256', 13 | name: 'chainId' 14 | }, 15 | { 16 | type: 'address', 17 | name: 'verifyingContract' 18 | } 19 | ], 20 | SafeTx: [ 21 | { type: 'address', name: 'to' }, 22 | { type: 'uint256', name: 'value' }, 23 | { type: 'bytes', name: 'data' }, 24 | { type: 'uint8', name: 'operation' }, 25 | { type: 'uint256', name: 'safeTxGas' }, 26 | { type: 'uint256', name: 'baseGas' }, 27 | { type: 'uint256', name: 'gasPrice' }, 28 | { type: 'address', name: 'gasToken' }, 29 | { type: 'address', name: 'refundReceiver' }, 30 | { type: 'uint256', name: 'nonce' } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Bug report about the Safe Account Abstraction SDK 4 | --- 5 | 6 | ## Prerequisites 7 | 8 | - First, many thanks for taking part in the community and helping us improve. We appreciate that a lot. 9 | - Support questions are better asked in our Discord chat: https://chat.safe.global/ 10 | - Please ensure the issue isn't already reported. 11 | 12 | _Please delete the above section and the instructions in the sections below before submitting_ 13 | 14 | ## Description 15 | 16 | Please describe concisely the bug you have found. 17 | 18 | ## Environment 19 | 20 | - Safe Account Abstraction SDK version: 21 | - Safe contract version: 22 | - Environment: 23 | - browser 24 | - non-browser 25 | 26 | ## Steps to reproduce 27 | 28 | If applicable, please provide a screenshot or small video reproducing the bug. 29 | Provide as much information as necessary to reproduce the bug. 30 | 31 | ## Expected result 32 | 33 | Please describe concisely what you expect instead. 34 | 35 | ## Additional context 36 | 37 | Add any other context about the problem here. 38 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/src/server.ts: -------------------------------------------------------------------------------- 1 | import express, { Application, Router, Request, Response } from 'express' 2 | import cors from 'cors' 3 | 4 | import logger, { log } from './lib/logger/logger' 5 | 6 | export type RequestType = Request 7 | export type ResponseType = Response 8 | 9 | class Server { 10 | app: Application 11 | 12 | constructor() { 13 | this.app = express() 14 | this.app.use(express.json()) 15 | this.app.use(logger) 16 | } 17 | 18 | start(serverPort: string) { 19 | this.app.listen(serverPort, () => { 20 | log.info(`Server running on port: ${serverPort}`) 21 | }) 22 | } 23 | 24 | registerRoutes(routes: Router[]) { 25 | routes.forEach((route) => { 26 | this.app.use(route) 27 | }) 28 | } 29 | 30 | configureCors(origins?: string[]) { 31 | this.app.options('*', cors()) 32 | this.app.post( 33 | '*', 34 | cors({ 35 | origin: origins 36 | }) 37 | ) 38 | this.app.get( 39 | '*', 40 | cors({ 41 | origin: origins 42 | }) 43 | ) 44 | } 45 | } 46 | 47 | export default Server 48 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Safe Ecosystem Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "account-abstraction-sdk", 3 | "private": true, 4 | "scripts": { 5 | "clean": "lerna clean && rm -rf ./node_modules", 6 | "format:check": "lerna run format:check", 7 | "format": "prettier --write */**/*.{js,json,md,ts}", 8 | "unbuild": "lerna run unbuild", 9 | "build": "lerna run build --stream", 10 | "test": "FORCE_COLOR=1 lerna run test --stream", 11 | "play": "ts-node ./playground/config/run.ts", 12 | "lint:check": "eslint './packages/**/*.{js,jsx,ts,tsx}'" 13 | }, 14 | "workspaces": { 15 | "packages": [ 16 | "packages/*" 17 | ] 18 | }, 19 | "author": "Safe (https://safe.global)", 20 | "license": "MIT", 21 | "devDependencies": { 22 | "@types/node": "^18.11.18", 23 | "@typescript-eslint/eslint-plugin": "^5.49.0", 24 | "@typescript-eslint/parser": "^5.49.0", 25 | "eslint": "^8.32.0", 26 | "eslint-config-prettier": "^8.6.0", 27 | "eslint-plugin-prettier": "^4.2.1", 28 | "lerna": "^6.4.1", 29 | "prettier": "^2.8.3", 30 | "ts-node": "^10.9.1", 31 | "typescript": "^4.9.4" 32 | }, 33 | "resolutions": { 34 | "@ethereumjs/tx": "4.0.2" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/auth-kit/README.md: -------------------------------------------------------------------------------- 1 | # Auth Kit 2 | 3 | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Fauth-kit.svg)](https://badge.fury.io/js/%40safe-global%2Fauth-kit) 4 | [![GitHub Release](https://img.shields.io/github/release/safe-global/account-abstraction-sdk.svg?style=flat)](https://github.com/safe-global/account-abstraction-sdk/releases) 5 | [![GitHub](https://img.shields.io/github/license/safe-global/account-abstraction-sdk)](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md) 6 | 7 | The Auth Kit provides a way to authenticate blockchain accounts using email addresses, social accounts or traditional web3 wallets (ex. Metamask). When using web2 methods as your email or social account, a derived Ethereum address will be generated. 8 | 9 | ## Reference 10 | 11 | - [Auth Kit docs](https://docs.safe.global/learn/safe-core-account-abstraction-sdk/auth-kit) 12 | 13 | ## Example 14 | 15 | [Check a functional demo](https://github.com/safe-global/account-abstraction-sdk/tree/dev/packages/auth-kit/example) using the `auth-kit` 16 | 17 | ## License 18 | 19 | This library is [released under MIT](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md). -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/src/controllers/stripe-controller.ts: -------------------------------------------------------------------------------- 1 | import { RequestType, ResponseType } from 'src/server' 2 | import stripeService from '../services/stripe-service' 3 | 4 | const HTTP_ERROR_STATUS = 400 5 | 6 | async function getStripeClientSecret(request: RequestType, response: ResponseType) { 7 | const { walletAddress, networks } = request.body 8 | 9 | try { 10 | const stripeResponse = await stripeService.getStripeClientSecret(walletAddress, networks) 11 | 12 | return response.send(stripeResponse) 13 | } catch (error: any) { 14 | response.status(HTTP_ERROR_STATUS) 15 | 16 | return response.send(error.response.data) 17 | } 18 | } 19 | 20 | async function getStripeSession(request: RequestType, response: ResponseType) { 21 | const { sessionId } = request.params 22 | 23 | try { 24 | const stripeResponse = await stripeService.getStripeSession(sessionId) 25 | 26 | return response.send(stripeResponse) 27 | } catch (error: any) { 28 | response.status(HTTP_ERROR_STATUS) 29 | 30 | return response.send(error.response.data) 31 | } 32 | } 33 | 34 | const stripeController = { 35 | getStripeClientSecret, 36 | getStripeSession 37 | } 38 | 39 | export default stripeController 40 | -------------------------------------------------------------------------------- /packages/relay-kit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@safe-global/relay-kit", 3 | "version": "0.1.0-alpha.2", 4 | "description": "Relay library to abstract transaction gas fees", 5 | "main": "dist/src/index.js", 6 | "typings": "dist/src/index.d.ts", 7 | "scripts": { 8 | "format:check": "prettier --check \"*/**/*.{js,json,md,ts}\"", 9 | "format": "prettier --write */**/*.{js,json,md,ts}", 10 | "unbuild": "rm -rf dist", 11 | "build": "rm -rf dist && yarn tsc", 12 | "test": "echo \"Error: no test specified\"" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/safe-global/account-abstraction-sdk.git" 17 | }, 18 | "keywords": [ 19 | "Safe", 20 | "Ethereum", 21 | "Account Abstraction", 22 | "SDK", 23 | "Relay" 24 | ], 25 | "author": "Safe (https://safe.global)", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/safe-global/account-abstraction-sdk/issues" 29 | }, 30 | "files": [ 31 | "dist" 32 | ], 33 | "homepage": "https://github.com/safe-global/account-abstraction-sdk#readme", 34 | "publishConfig": { 35 | "access": "public" 36 | }, 37 | "dependencies": { 38 | "@gelatonetwork/relay-sdk": "^3.1.0", 39 | "ethers": "^5.7.2" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/onramp-kit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@safe-global/onramp-kit", 3 | "version": "0.1.0-alpha.2", 4 | "description": "Onramp library", 5 | "main": "dist/src/index.js", 6 | "types": "dist/src/index.d.ts", 7 | "scripts": { 8 | "format:check": "prettier --check \"*/**/*.{js,json,md,ts}\"", 9 | "format": "prettier --write */**/*.{js,json,md,ts}", 10 | "unbuild": "rm -rf dist", 11 | "build": "rm -rf dist && yarn tsc", 12 | "test": "echo \"Error: no test specified\"" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/safe-global/account-abstraction-sdk.git" 17 | }, 18 | "keywords": [ 19 | "Safe", 20 | "Ethereum", 21 | "Account Abstraction", 22 | "SDK", 23 | "Onramp" 24 | ], 25 | "author": "Safe (https://safe.global)", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/safe-global/account-abstraction-sdk/issues" 29 | }, 30 | "files": [ 31 | "dist" 32 | ], 33 | "homepage": "https://github.com/safe-global/account-abstraction-sdk#readme", 34 | "publishConfig": { 35 | "access": "public" 36 | }, 37 | "devDependencies": { 38 | "@testing-library/jest-dom": "^5.16.5" 39 | }, 40 | "dependencies": { 41 | "@ethersproject/address": "^5.7.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/auth-kit/example/src/AppBar.tsx: -------------------------------------------------------------------------------- 1 | import { AppBar as MuiAppBar, Typography, styled, Box, Button } from '@mui/material' 2 | 3 | type AppBarProps = { 4 | isLoggedIn: boolean 5 | onLogin: () => void 6 | onLogout: () => void 7 | } 8 | 9 | const AppBar = ({ isLoggedIn, onLogin, onLogout }: AppBarProps) => { 10 | return ( 11 | 12 | 13 | Auth Provider Demo 14 | 15 | 16 | 17 | {isLoggedIn ? ( 18 | 21 | ) : ( 22 | 25 | )} 26 | 27 | 28 | ) 29 | } 30 | 31 | const StyledAppBar = styled(MuiAppBar)` 32 | && { 33 | position: sticky; 34 | top: 0; 35 | background: ${({ theme }) => theme.palette.background.paper}; 36 | height: 70px; 37 | align-items: center; 38 | justify-content: space-between; 39 | flex-direction: row; 40 | border-bottom: 2px solid ${({ theme }) => theme.palette.background.paper}; 41 | box-shadow: none; 42 | } 43 | ` 44 | 45 | export default AppBar 46 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/README.md: -------------------------------------------------------------------------------- 1 | # Safe Account Abstraction SDK 2 | 3 | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Faccount-abstraction.svg)](https://badge.fury.io/js/%40safe-global%2Faccount-abstraction-kit-poc) 4 | [![GitHub Release](https://img.shields.io/github/release/safe-global/account-abstraction-sdk.svg?style=flat)](https://github.com/safe-global/account-abstraction-sdk/releases) 5 | [![GitHub](https://img.shields.io/github/license/safe-global/account-abstraction-sdk)](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md) 6 | 7 | Description TBD 8 | 9 | ## Table of contents 10 | 11 | - [Installation](#installation) 12 | - [Build](#build) 13 | - [Initialization](#initialization) 14 | - [License](#license) 15 | 16 | ## Installation 17 | 18 | Install the package with yarn or npm: 19 | 20 | ```bash 21 | yarn install 22 | npm install 23 | ``` 24 | 25 | ## Build 26 | 27 | Build the package with yarn or npm: 28 | 29 | ```bash 30 | yarn build 31 | npm build 32 | ``` 33 | 34 | ## Initialization 35 | 36 | Initialization TBD 37 | 38 | ```js 39 | 40 | ``` 41 | 42 | ## License 43 | 44 | This library is [released under MIT](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md). 45 | -------------------------------------------------------------------------------- /packages/auth-kit/example/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/src/services/stripe-service.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosInstance } from 'axios' 2 | import dotenv from 'dotenv' 3 | 4 | type stripeSuccessType = Promise<{ 5 | clientSecret: string 6 | }> 7 | 8 | type stripeErrorType = any 9 | 10 | dotenv.config() 11 | 12 | const { STRIPE_SERVER_SECRET_KEY } = process.env 13 | 14 | const STRIPE_BASE_URL = 'https://api.stripe.com' 15 | const GET_STRIPE_CLIENT_SECRET_PATH = 'v1/crypto/onramp_sessions' 16 | 17 | const axiosStripeAPI: AxiosInstance = axios.create({ 18 | baseURL: STRIPE_BASE_URL, 19 | headers: { 20 | Authorization: `Bearer ${STRIPE_SERVER_SECRET_KEY}`, 21 | 'content-type': 'application/x-www-form-urlencoded' 22 | } 23 | }) 24 | 25 | async function getStripeClientSecret( 26 | walletAddress: string, 27 | supportedNetworks: string[] 28 | ): Promise { 29 | const { data } = await axiosStripeAPI.post(GET_STRIPE_CLIENT_SECRET_PATH, { 30 | transaction_details: { 31 | wallet_address: walletAddress, 32 | lock_wallet_address: true, 33 | supported_destination_networks: supportedNetworks 34 | } 35 | }) 36 | 37 | return data 38 | } 39 | 40 | async function getStripeSession(sessionId: string) { 41 | const { data } = await axiosStripeAPI.get( 42 | `${GET_STRIPE_CLIENT_SECRET_PATH}/${sessionId}` 43 | ) 44 | 45 | return data 46 | } 47 | 48 | const stripeService = { 49 | getStripeClientSecret, 50 | getStripeSession 51 | } 52 | 53 | export default stripeService 54 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@safe-global/account-abstraction-kit-poc", 3 | "version": "0.1.0-alpha.1", 4 | "description": "Safe Account Abstraction", 5 | "main": "dist/src/index.js", 6 | "typings": "dist/src/index.d.ts", 7 | "scripts": { 8 | "format:check": "prettier --check \"*/**/*.{js,json,md,ts}\"", 9 | "format": "prettier --write */**/*.{js,json,md,ts}", 10 | "unbuild": "rm -rf dist typechain", 11 | "build": "rm -rf dist && ts-node ./scripts/typechain && yarn tsc", 12 | "test": "echo \"Error: no test specified\"" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/safe-global/account-abstraction-sdk.git" 17 | }, 18 | "keywords": [ 19 | "Safe", 20 | "Ethereum", 21 | "Account Abstraction", 22 | "SDK" 23 | ], 24 | "author": "Safe (https://safe.global)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/safe-global/account-abstraction-sdk/issues" 28 | }, 29 | "files": [ 30 | "dist" 31 | ], 32 | "homepage": "https://github.com/safe-global/account-abstraction-sdk#readme", 33 | "publishConfig": { 34 | "access": "public" 35 | }, 36 | "devDependencies": { 37 | "@typechain/ethers-v5": "^10.2.0", 38 | "typechain": "^8.1.1" 39 | }, 40 | "dependencies": { 41 | "@gnosis.pm/safe-contracts": "^1.3.0", 42 | "@safe-global/relay-kit": "^0.1.0-alpha.2", 43 | "@safe-global/safe-deployments": "^1.20.2", 44 | "ethereumjs-util": "^7.1.5", 45 | "ethers": "^5.7.2" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/auth-kit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@safe-global/auth-kit", 3 | "version": "0.1.0-alpha.2", 4 | "description": "Authentication library for web2 logins", 5 | "main": "dist/src/index.js", 6 | "types": "dist/src/index.d.ts", 7 | "scripts": { 8 | "format:check": "prettier --check \"*/**/*.{js,json,md,ts}\"", 9 | "format": "prettier --write */**/*.{js,json,md,ts}", 10 | "unbuild": "rm -rf dist", 11 | "build": "rm -rf dist && yarn tsc", 12 | "test": "echo \"Error: no test specified\"" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/safe-global/account-abstraction-sdk.git" 17 | }, 18 | "keywords": [ 19 | "Safe", 20 | "Ethereum", 21 | "Account Abstraction", 22 | "SDK", 23 | "Authentication" 24 | ], 25 | "author": "Safe (https://safe.global)", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/safe-global/account-abstraction-sdk/issues" 29 | }, 30 | "files": [ 31 | "dist" 32 | ], 33 | "homepage": "https://github.com/safe-global/account-abstraction-sdk#readme", 34 | "publishConfig": { 35 | "access": "public" 36 | }, 37 | "devDependencies": { 38 | "@testing-library/jest-dom": "^5.16.5", 39 | "@web3auth/base": "^4.3.0", 40 | "@web3auth/modal": "^4.3.1", 41 | "@web3auth/openlogin-adapter": "^4.3.0" 42 | }, 43 | "dependencies": { 44 | "@safe-global/safe-ethers-lib": "^1.9.1", 45 | "@safe-global/safe-service-client": "^1.5.1", 46 | "@walletconnect/client": "^1.8.0", 47 | "ethers": "^5.7.2", 48 | "events": "^3.3.0" 49 | }, 50 | "peerDependencies": { 51 | "@web3auth/base": "^4.3.0", 52 | "@web3auth/modal": "^4.3.1", 53 | "@web3auth/openlogin-adapter": "^4.3.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/utils/signatures.ts: -------------------------------------------------------------------------------- 1 | import { TypedDataSigner } from '@ethersproject/abstract-signer' 2 | import { Signer } from 'ethers' 3 | import { EIP712_SAFE_TX_TYPES } from '../constants' 4 | import { SafeTransactionData, SafeTxTypedData } from '../types' 5 | 6 | export function isTypedDataSigner(signer: any): signer is TypedDataSigner { 7 | return (signer as unknown as TypedDataSigner)._signTypedData !== undefined 8 | } 9 | 10 | export function getSignTypedData( 11 | safeAddress: string, 12 | transaction: SafeTransactionData, 13 | chainId: number 14 | ): SafeTxTypedData { 15 | return { 16 | types: EIP712_SAFE_TX_TYPES, 17 | domain: { 18 | chainId, 19 | verifyingContract: safeAddress 20 | }, 21 | primaryType: 'SafeTx', 22 | message: { 23 | to: transaction.to, 24 | value: transaction.value.toString(), 25 | data: transaction.data, 26 | operation: transaction.operation, 27 | safeTxGas: transaction.safeTxGas.toString(), 28 | baseGas: transaction.baseGas.toString(), 29 | gasPrice: transaction.gasPrice.toString(), 30 | gasToken: transaction.gasToken, 31 | refundReceiver: transaction.refundReceiver, 32 | nonce: transaction.nonce.toString() 33 | } 34 | } 35 | } 36 | 37 | export async function getSignature( 38 | signer: Signer, 39 | safeAddress: string, 40 | transaction: SafeTransactionData, 41 | chainId: number 42 | ): Promise { 43 | const typedData = getSignTypedData(safeAddress, transaction, chainId) 44 | let signature = '' 45 | if (isTypedDataSigner(signer)) { 46 | signature = await signer._signTypedData( 47 | typedData.domain, 48 | { SafeTx: typedData.types.SafeTx }, 49 | typedData.message 50 | ) 51 | } 52 | return signature 53 | } 54 | -------------------------------------------------------------------------------- /packages/onramp-kit/README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ Warning ⚠️ 2 | 3 | This package is provided for testing purposes only. It's not ready for production use. We are working with Stripe and participating in the pilot test for their new [crypto on-ramp](https://stripe.com/es/blog/crypto-onramp). Considering this, we provide a public key and a testing server already configured during the [Safe Account Abstraction hackathon](https://gnosis-safe.notion.site/Safe-d6c6ed61389041e28f5c7c925f653701) 4 | 5 | Once the hackathon and Stripe pilot are over, the server will be removed and you should use your own keys and server in case you opt-in for the [StripeAdapter](https://github.com/safe-global/account-abstraction-sdk/blob/195588a4388b15f06b05d2027ffd43185781be34/packages/onramp-kit/src/adapters/StripeAdapter.ts). 6 | 7 | # OnRamp Kit 8 | 9 | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Fonramp-kit.svg)](https://badge.fury.io/js/%40safe-global%2Fonramp-kit) 10 | [![GitHub Release](https://img.shields.io/github/release/safe-global/account-abstraction-sdk.svg?style=flat)](https://github.com/safe-global/account-abstraction-sdk/releases) 11 | [![GitHub](https://img.shields.io/github/license/safe-global/account-abstraction-sdk)](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md) 12 | 13 | The Onramp Kit allows users to buy cryptocurrencies using a credit card and other payment options. 14 | 15 | ## Reference 16 | 17 | - [OnRamp Kit docs](https://docs.safe.global/learn/safe-core-account-abstraction-sdk/onramp-kit) 18 | 19 | ## Example 20 | 21 | [Check a functional demo](https://github.com/safe-global/account-abstraction-sdk/tree/195588a4388b15f06b05d2027ffd43185781be34/packages/onramp-kit/example) using the `onramp-kit` 22 | 23 | ## License 24 | 25 | This library is [released under MIT](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md). -------------------------------------------------------------------------------- /packages/onramp-kit/src/SafeOnRampKit.ts: -------------------------------------------------------------------------------- 1 | import StripeAdapter from './adapters/stripe/StripeAdapter' 2 | import type { SafeOnRampConfig, SafeOnRampClient, SafeOnRampOpenOptions } from './types' 3 | 4 | import { SafeOnRampProviderType } from './types/onRamp' 5 | 6 | /** 7 | * This class allows to initialize the Safe OnRamp Kit for convert fiat to crypto 8 | * @class SafeOnRampKit 9 | */ 10 | export class SafeOnRampKit { 11 | #client: SafeOnRampClient 12 | 13 | /** 14 | * Initialize the SafeOnRampKit 15 | * @constructor 16 | * @param client - The client implementing the SafeOnRampClient interface 17 | */ 18 | constructor(client: SafeOnRampClient) { 19 | this.#client = client 20 | } 21 | 22 | /** 23 | * 24 | * @param providerType The provider service to use. Currently only Stripe is supported 25 | * @param config The configuration object including the specific provider options 26 | * @returns A SafeOnRampKit instance 27 | * @throws Error if the provider type is not supported 28 | */ 29 | static async init(providerType: SafeOnRampProviderType, config: SafeOnRampConfig) { 30 | let client 31 | 32 | switch (providerType) { 33 | case SafeOnRampProviderType.Stripe: 34 | client = new StripeAdapter(config.onRampProviderConfig) 35 | break 36 | default: 37 | throw new Error('Provider type not supported') 38 | } 39 | 40 | await client.init() 41 | 42 | return new SafeOnRampKit(client) 43 | } 44 | 45 | /** 46 | * This method opens the onramp widget using the provided options 47 | * @param options The options to open the onramp widget 48 | */ 49 | async open(options: SafeOnRampOpenOptions): Promise { 50 | return await this.#client.open(options) 51 | } 52 | 53 | /** 54 | * This method destroys the onramp widget 55 | */ 56 | async close() { 57 | await this.#client.close() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/types/stripe.ts: -------------------------------------------------------------------------------- 1 | interface QuoteCurrency { 2 | id: string 3 | asset_code: string 4 | asset_display_name: string 5 | currency_minor_units: number 6 | currency_network: string 7 | currency_symbol: string 8 | currency_symbol_location: string 9 | } 10 | 11 | interface Fees { 12 | network_fee: string 13 | network_fee_monetary: string 14 | total_fee: string 15 | transaction_fee: string 16 | transaction_fee_monetary: string 17 | } 18 | 19 | interface Quote { 20 | blockchain_tx_id: string 21 | destination_amount: string | null 22 | destination_crypto_amount: string | null 23 | destination_currency: QuoteCurrency | null 24 | expiration: number 25 | fees: Fees 26 | fixed_currency_side: string 27 | source_amount: string | null 28 | source_currency: QuoteCurrency | null 29 | source_monetary_amount: string | null 30 | time_to_expiration: number 31 | total_amount: string 32 | } 33 | 34 | interface FixedTransactionDetails { 35 | destination_amount: string | null 36 | destination_crypto_amount: string | null 37 | destination_currency: string | null 38 | destination_network: string | null 39 | lock_wallet_address: boolean 40 | source_amount: string | null 41 | source_currency: string | null 42 | source_monetary_amount: string | null 43 | supported_destination_currencies: string[] 44 | supported_destination_networks: string[] 45 | wallet_address: string 46 | wallet_addresses: any 47 | } 48 | 49 | export interface Session { 50 | id: string 51 | object: string 52 | livemode: boolean 53 | client_secret: string 54 | quote: Quote 55 | wallet_address: string 56 | fixed_transaction_details: FixedTransactionDetails 57 | status: string 58 | } 59 | 60 | interface Payload { 61 | session: Session 62 | } 63 | 64 | export interface OnrampSessionUpdatedEvent { 65 | type: string 66 | payload: Payload 67 | } 68 | 69 | export interface StripeProviderConfig { 70 | stripePublicKey: string 71 | onRampBackendUrl: string 72 | } 73 | 74 | export interface StripeSession { 75 | mount: (element: string) => void 76 | addEventListener: (event: string, callback: (e: any) => void) => void 77 | removeEventListener: (event: string, callback: (e: any) => void) => void 78 | } 79 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/types/index.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@ethersproject/bignumber' 2 | 3 | export enum OperationType { 4 | Call, 5 | DelegateCall 6 | } 7 | 8 | export interface AccountAbstractionConfig { 9 | relayAdapter: RelayAdapter 10 | } 11 | 12 | export interface MetaTransactionData { 13 | to: string 14 | value: BigNumber 15 | data: string 16 | operation?: OperationType 17 | } 18 | 19 | export interface SafeTransactionData extends MetaTransactionData { 20 | operation: OperationType 21 | safeTxGas: BigNumber 22 | baseGas: BigNumber 23 | gasPrice: BigNumber 24 | gasToken: string 25 | refundReceiver: string 26 | nonce: number 27 | } 28 | 29 | // TO-DO: Duplicated. Remove local type and import from "types" package 30 | // { 31 | 32 | export interface MetaTransactionOptions { 33 | gasLimit: BigNumber 34 | gasToken?: string 35 | isSponsored?: boolean 36 | } 37 | 38 | export interface RelayTransaction { 39 | target: string 40 | encodedTransaction: string 41 | chainId: number 42 | options: MetaTransactionOptions 43 | } 44 | 45 | // import { RelayResponse } from '@gelatonetwork/relay-sdk' 46 | export interface RelayResponse { 47 | taskId: string 48 | } 49 | 50 | export interface RelayAdapter { 51 | getFeeCollector(): string 52 | getEstimateFee(chainId: number, gasLimit: BigNumber, gasToken?: string): Promise 53 | relayTransaction(transaction: RelayTransaction): Promise 54 | } 55 | 56 | // } 57 | // TO-DO: Duplicated. Remove local type and import from "types" package 58 | 59 | export interface SafeSetupConfig { 60 | owners: string[] 61 | threshold: number 62 | fallbackHandlerAddress: string 63 | } 64 | 65 | interface Eip712MessageTypes { 66 | EIP712Domain: { 67 | type: string 68 | name: string 69 | }[] 70 | SafeTx: { 71 | type: string 72 | name: string 73 | }[] 74 | } 75 | 76 | export interface SafeTxTypedData { 77 | types: Eip712MessageTypes 78 | domain: { 79 | chainId?: number 80 | verifyingContract: string 81 | } 82 | primaryType: 'SafeTx' 83 | message: { 84 | to: string 85 | value: string 86 | data: string 87 | operation: OperationType 88 | safeTxGas: string 89 | baseGas: string 90 | gasPrice: string 91 | gasToken: string 92 | refundReceiver: string 93 | nonce: string 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /tsconfig.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 4 | "module": "CommonJS", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 5 | "allowJs": false, /* Allow javascript files to be compiled. */ 6 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 7 | "sourceMap": true, /* Generates corresponding '.map' file. */ 8 | "strict": true, /* Enable all strict type-checking options. */ 9 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 10 | "strictNullChecks": true, /* Enable strict null checks. */ 11 | "strictFunctionTypes": true, /* Enable strict checking of function types. */ 12 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 13 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 14 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 15 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 16 | "noUnusedParameters": true, /* Report errors on unused parameters. */ 17 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 18 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 19 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 20 | "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 21 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 22 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 23 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 24 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ 25 | "resolveJsonModule": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [DEPRECATED] Safe Account Abstraction SDK 2 | 3 | ATTENTION: please find the current version of this code in [Safe Core SDK](https://github.com/safe-global/safe-core-sdk) repository 4 | 5 | [![GitHub](https://img.shields.io/github/license/safe-global/account-abstraction-sdk)](https://github.com/safe-global/account-abstraction-sdk/blob/main/LICENSE.md) 6 | 7 | DESCRIPTION TBD 8 | 9 | ## Packages 10 | 11 | | Package | Release | Description | 12 | | ------- | :-----: | ----------- | 13 | | [account-abstraction](https://github.com/safe-global/account-abstraction-sdk/tree/main/packages/account-abstraction-kit) | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Fsafe-core.svg)](https://badge.fury.io/js/%40safe-global%2Faccount-abstraction-kit-poc) | TBD | 14 | | [auth-kit](https://github.com/safe-global/account-abstraction-sdk/tree/main/packages/auth-kit) | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Fauth-kit.svg)](https://badge.fury.io/js/%40safe-global%2Fauth-kit) | Enable web2 logins for blockchain accounts | 15 | | [onramp-kit](https://github.com/safe-global/account-abstraction-sdk/tree/main/packages/onramp-kit) | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Fonramp-kit.svg)](https://badge.fury.io/js/%40safe-global%2Fonramp-kit) | Enable transition from fiat to crypto | 16 | | [relay-kit](https://github.com/safe-global/account-abstraction-sdk/tree/main/packages/relay-kit) | [![NPM Version](https://badge.fury.io/js/%40safe-global%2Frelay-kit.svg)](https://badge.fury.io/js/%40safe-global%2Frelay-kit) | Abstract Safe signers from transaction gas | 17 | 18 | 19 | ## Installation 20 | 21 | Install the package with yarn or npm: 22 | 23 | ```bash 24 | yarn install 25 | npm install 26 | ``` 27 | 28 | ## Build 29 | 30 | Build the package with yarn or npm: 31 | 32 | ```bash 33 | yarn build 34 | npm build 35 | ``` 36 | 37 | ## Playground 38 | 39 | This project includes a [playground](https://github.com/safe-global/account-abstraction-sdk/tree/main/playground) with a few scripts that can be used as a starting point to use the Safe Account Abstraction SDK. 40 | 41 | #### Check all the scripts in the playground 42 | 43 | ```bash 44 | yarn play 45 | ``` 46 | 47 | #### 1. Execute meta-transaction via Gelato Relay paid with balance in the Safe 48 | 49 | ```bash 50 | yarn play paid-transaction 51 | ``` 52 | 53 | #### 2. Execute meta-transaction via Gelato Relay paid by 1Balance deposit 54 | 55 | ```bash 56 | yarn play sponsored-transaction 57 | ``` 58 | -------------------------------------------------------------------------------- /.github/workflows/cla.yml: -------------------------------------------------------------------------------- 1 | name: 'CLA Assistant' 2 | on: 3 | issue_comment: 4 | types: [created] 5 | pull_request_target: 6 | types: [opened, closed, synchronize] 7 | 8 | jobs: 9 | CLAssistant: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: 'CLA Assistant' 13 | if: (github.event.comment.body == 'recheckcla' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' 14 | # Beta Release 15 | uses: contributor-assistant/github-action@v2.2.0 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | # the below token should have repo scope and must be manually added by you in the repository's secret 19 | PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_ACCESS_TOKEN }} 20 | with: 21 | path-to-signatures: 'signatures/version1/cla.json' 22 | path-to-document: 'https://safe.global/cla/' # e.g. a CLA or a DCO document 23 | # branch should not be protected 24 | branch: 'main' 25 | # user names of users allowed to contribute without CLA 26 | allowlist: germartinez,rmeissner,Uxio0,dasanra,luarx,DaniSomoza,yagopv,JagoFigueroa,bot* 27 | 28 | # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken 29 | # enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository) 30 | remote-organization-name: 'safe-global' 31 | # enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository) 32 | remote-repository-name: 'cla-signatures' 33 | #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' 34 | #signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo' 35 | #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' 36 | #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' 37 | #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' 38 | #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) 39 | #use-dco-flag: true - If you are using DCO instead of CLA 40 | -------------------------------------------------------------------------------- /packages/auth-kit/src/adapters/Web3AuthAdapter.ts: -------------------------------------------------------------------------------- 1 | import { CHAIN_NAMESPACES } from '@web3auth/base' 2 | import { Web3Auth } from '@web3auth/modal' 3 | import { OpenloginAdapter } from '@web3auth/openlogin-adapter' 4 | import { ExternalProvider } from '@ethersproject/providers' 5 | 6 | import type { SafeAuthClient, Web3AuthProviderConfig } from '../types' 7 | 8 | /** 9 | * Web3AuthAdapter implements the SafeAuthClient interface for adapting the Web3Auth service provider 10 | * @class 11 | */ 12 | export default class Web3AuthAdapter implements SafeAuthClient { 13 | provider: ExternalProvider | null 14 | private chainId: string 15 | private web3authInstance?: Web3Auth 16 | private config: Web3AuthProviderConfig 17 | 18 | /** 19 | * 20 | * @param chainId Chain Id 21 | * @param config Web3Auth configuration 22 | */ 23 | constructor(chainId: string, config: Web3AuthProviderConfig) { 24 | this.config = config 25 | this.chainId = chainId 26 | this.provider = null 27 | } 28 | 29 | /** 30 | * Initialize the Web3Auth service provider {@link https://web3auth.io/docs/sdk/web/modal/initialize} 31 | * @throws Error if there was an error initializing Web3Auth 32 | */ 33 | async init() { 34 | try { 35 | const web3auth = new Web3Auth({ 36 | clientId: this.config.clientId, 37 | web3AuthNetwork: this.config.network, 38 | chainConfig: { 39 | chainNamespace: CHAIN_NAMESPACES.EIP155, 40 | chainId: this.chainId, 41 | rpcTarget: this.config.rpcTarget 42 | }, 43 | uiConfig: { 44 | theme: this.config.theme, 45 | loginMethodsOrder: ['google', 'facebook'] 46 | } 47 | }) 48 | 49 | const openloginAdapter = new OpenloginAdapter({ 50 | loginSettings: { 51 | mfaLevel: 'none' 52 | }, 53 | adapterSettings: { 54 | uxMode: 'popup', 55 | whiteLabel: { 56 | name: 'Safe' 57 | } 58 | } 59 | }) 60 | 61 | web3auth.configureAdapter(openloginAdapter) 62 | 63 | await web3auth.initModal() 64 | 65 | this.provider = web3auth.provider 66 | this.web3authInstance = web3auth 67 | } catch { 68 | throw new Error('There was an error initializing Web3Auth') 69 | } 70 | } 71 | 72 | /** 73 | * Connect to the Web3Auth service provider 74 | * @returns 75 | */ 76 | async signIn(): Promise { 77 | if (!this.web3authInstance) return 78 | 79 | this.provider = await this.web3authInstance.connect() 80 | } 81 | 82 | /** 83 | * Disconnect from the Web3Auth service provider 84 | */ 85 | async signOut(): Promise { 86 | if (!this.web3authInstance) return 87 | 88 | return await this.web3authInstance?.logout() 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /packages/relay-kit/src/GelatoRelayAdapter.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@ethersproject/bignumber' 2 | import { 3 | CallWithSyncFeeRequest, 4 | GelatoRelay as GelatoNetworkRelay, 5 | RelayRequestOptions, 6 | RelayResponse, 7 | SponsoredCallRequest, 8 | TransactionStatusResponse 9 | } from '@gelatonetwork/relay-sdk' 10 | import { GELATO_FEE_COLLECTOR, GELATO_NATIVE_TOKEN_ADDRESS, ZERO_ADDRESS } from './constants' 11 | import { MetaTransactionOptions, RelayAdapter, RelayTransaction } from './types' 12 | 13 | export class GelatoRelayAdapter implements RelayAdapter { 14 | #gelatoRelay: GelatoNetworkRelay 15 | #apiKey?: string 16 | 17 | constructor(apiKey?: string) { 18 | this.#gelatoRelay = new GelatoNetworkRelay() 19 | this.#apiKey = apiKey 20 | } 21 | 22 | private _getFeeToken(gasToken?: string): string { 23 | return !gasToken || gasToken === ZERO_ADDRESS ? GELATO_NATIVE_TOKEN_ADDRESS : gasToken 24 | } 25 | 26 | getFeeCollector(): string { 27 | return GELATO_FEE_COLLECTOR 28 | } 29 | 30 | async getEstimateFee( 31 | chainId: number, 32 | gasLimit: BigNumber, 33 | gasToken?: string 34 | ): Promise { 35 | const feeToken = this._getFeeToken(gasToken) 36 | const estimation = await this.#gelatoRelay.getEstimatedFee(chainId, feeToken, gasLimit, true) 37 | return estimation 38 | } 39 | 40 | async getTaskStatus(taskId: string): Promise { 41 | return await this.#gelatoRelay.getTaskStatus(taskId) 42 | } 43 | 44 | async sponsorTransaction( 45 | target: string, 46 | encodedTransaction: string, 47 | chainId: number 48 | ): Promise { 49 | if (!this.#apiKey) { 50 | throw new Error('API key not defined') 51 | } 52 | const request: SponsoredCallRequest = { 53 | chainId, 54 | target, 55 | data: encodedTransaction 56 | } 57 | const response = await this.#gelatoRelay.sponsoredCall(request, this.#apiKey) 58 | return response 59 | } 60 | 61 | async payTransaction( 62 | target: string, 63 | encodedTransaction: string, 64 | chainId: number, 65 | options: MetaTransactionOptions 66 | ): Promise { 67 | const { gasLimit, gasToken } = options 68 | const feeToken = this._getFeeToken(gasToken) 69 | const request: CallWithSyncFeeRequest = { 70 | chainId, 71 | target, 72 | data: encodedTransaction, 73 | feeToken, 74 | isRelayContext: false 75 | } 76 | const relayRequestOptions: RelayRequestOptions = { 77 | gasLimit: gasLimit && gasLimit.toString() 78 | } 79 | const response = await this.#gelatoRelay.callWithSyncFee(request, relayRequestOptions) 80 | return response 81 | } 82 | 83 | async relayTransaction({ 84 | target, 85 | encodedTransaction, 86 | chainId, 87 | options 88 | }: RelayTransaction): Promise { 89 | const response = options.isSponsored 90 | ? this.sponsorTransaction(target, encodedTransaction, chainId) 91 | : this.payTransaction(target, encodedTransaction, chainId, options) 92 | return response 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/client/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState, useRef } from 'react' 2 | import { isAddress } from '@ethersproject/address' 3 | import { SafeOnRampKit, SafeOnRampEvent, SafeOnRampProviderType } from '../../../src' 4 | import { Grid, TextField, Button } from '@mui/material' 5 | 6 | import AppBar from './AppBar' 7 | 8 | const isSessionValid = (sessionId: string) => sessionId.length === 28 9 | 10 | function App() { 11 | const [walletAddress, setWalletAddress] = useState('') 12 | const [sessionId, setSessionId] = useState('') 13 | const [onRampClient, setOnRampClient] = useState() 14 | const stripeRootRef = useRef(null) 15 | 16 | const handleCreateSession = async () => { 17 | if (!isSessionValid(sessionId) && !isAddress(walletAddress)) return 18 | 19 | if (stripeRootRef.current) { 20 | stripeRootRef.current.innerHTML = '' 21 | } 22 | 23 | const sessionData = (await onRampClient?.open({ 24 | sessionId: sessionId, 25 | walletAddress, 26 | networks: ['ethereum', 'polygon'], 27 | element: '#stripe-root', 28 | events: { 29 | onLoaded: () => console.log('onLoaded()'), 30 | onPaymentSuccessful: (eventData: SafeOnRampEvent) => 31 | console.log('onPaymentSuccessful(): ', eventData), 32 | onPaymentProcessing: (eventData: SafeOnRampEvent) => 33 | console.log('onPaymentProcessing(): ', eventData), 34 | onPaymentError: (eventData: SafeOnRampEvent) => console.log('onPaymentError(): ', eventData) 35 | } 36 | })) as any 37 | 38 | setWalletAddress(sessionData.transaction_details.wallet_address) 39 | } 40 | 41 | useEffect(() => { 42 | ;(async () => { 43 | const onRampClient = await SafeOnRampKit.init(SafeOnRampProviderType.Stripe, { 44 | onRampProviderConfig: { 45 | stripePublicKey: import.meta.env.VITE_STRIPE_PUBLIC_KEY, 46 | onRampBackendUrl: import.meta.env.VITE_SAFE_STRIPE_BACKEND_BASE_URL 47 | } 48 | }) 49 | 50 | setOnRampClient(onRampClient) 51 | })() 52 | }, []) 53 | 54 | return ( 55 | <> 56 | 57 | 58 | 59 | setWalletAddress(event.target.value)} 66 | sx={{ width: '100%' }} 67 | /> 68 | setSessionId(event.target.value)} 75 | sx={{ width: '100%', mt: 2 }} 76 | /> 77 |
78 | 81 |
82 | 83 |
84 |
85 |
86 | 87 | ) 88 | } 89 | 90 | export default App 91 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/utils/deployments.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DeploymentFilter, 3 | getCompatibilityFallbackHandlerDeployment, 4 | getMultiSendCallOnlyDeployment, 5 | getProxyFactoryDeployment, 6 | getSafeL2SingletonDeployment, 7 | getSafeSingletonDeployment 8 | } from '@safe-global/safe-deployments' 9 | import { ethers } from 'ethers' 10 | import { GnosisSafe__factory } from '../../typechain/factories' 11 | import { MultiSendCallOnly__factory } from '../../typechain/factories/libraries' 12 | import { GnosisSafeProxyFactory__factory } from '../../typechain/factories/proxies' 13 | import { GnosisSafe } from '../../typechain/GnosisSafe' 14 | import { MultiSendCallOnly } from './../../typechain/libraries/MultiSendCallOnly' 15 | import { GnosisSafeProxyFactory } from './../../typechain/proxies/GnosisSafeProxyFactory' 16 | 17 | export const safeDeploymentsL1ChainIds: number[] = [ 18 | 1 // Ethereum Mainnet 19 | ] 20 | 21 | export function getSafeContract( 22 | chainId: number, 23 | signer: ethers.Signer, 24 | isL1SafeMasterCopy = false 25 | ): GnosisSafe { 26 | const filters: DeploymentFilter = { 27 | version: '1.3.0', // Only Safe v1.3.0 supported so far 28 | network: chainId.toString(), 29 | released: true 30 | } 31 | const contractDeployment = 32 | safeDeploymentsL1ChainIds.includes(chainId) || isL1SafeMasterCopy 33 | ? getSafeSingletonDeployment(filters) 34 | : getSafeL2SingletonDeployment(filters) 35 | const contractAddress = contractDeployment?.networkAddresses[chainId] 36 | if (!contractAddress) { 37 | throw new Error('Invalid SafeProxy contract address') 38 | } 39 | const contract = GnosisSafe__factory.connect(contractAddress, signer) 40 | return contract 41 | } 42 | 43 | export function getSafeProxyFactoryContract( 44 | chainId: number, 45 | signer: ethers.Signer 46 | ): GnosisSafeProxyFactory { 47 | const contractDeployment = getProxyFactoryDeployment({ 48 | version: '1.3.0', // Only Safe v1.3.0 supported so far 49 | network: chainId.toString(), 50 | released: true 51 | }) 52 | const contractAddress = contractDeployment?.networkAddresses[chainId] 53 | if (!contractAddress) { 54 | throw new Error('Invalid SafeProxyFactory contract address') 55 | } 56 | const contract = GnosisSafeProxyFactory__factory.connect(contractAddress, signer) 57 | return contract 58 | } 59 | 60 | export function getMultiSendCallOnlyContract( 61 | chainId: number, 62 | signer: ethers.Signer 63 | ): MultiSendCallOnly { 64 | const contractDeployment = getMultiSendCallOnlyDeployment({ 65 | version: '1.3.0', // Only Safe v1.3.0 supported so far 66 | network: chainId.toString(), 67 | released: true 68 | }) 69 | const contractAddress = contractDeployment?.networkAddresses[chainId] 70 | if (!contractAddress) { 71 | throw new Error('Invalid MultiSendCallOnly contract address') 72 | } 73 | const contract = MultiSendCallOnly__factory.connect(contractAddress, signer) 74 | return contract 75 | } 76 | 77 | export function getCompatibilityFallbackHandlerAddress(chainId: number): string { 78 | const contractDeployment = getCompatibilityFallbackHandlerDeployment({ 79 | version: '1.3.0', // Only Safe v1.3.0 supported so far 80 | network: chainId.toString(), 81 | released: true 82 | }) 83 | const contractAddress = contractDeployment?.networkAddresses[chainId] 84 | if (!contractAddress) { 85 | throw new Error('Invalid CompatibilityFallbackHandler contract address') 86 | } 87 | return contractAddress 88 | } 89 | -------------------------------------------------------------------------------- /playground/relay-kit/sponsored-transaction.ts: -------------------------------------------------------------------------------- 1 | import AccountAbstraction, { 2 | MetaTransactionData, 3 | MetaTransactionOptions, 4 | OperationType 5 | } from '@safe-global/account-abstraction-kit-poc' 6 | import { GelatoRelayAdapter } from '@safe-global/relay-kit' 7 | import { BigNumber, ethers } from 'ethers' 8 | import { AccountAbstractionConfig } from './../../packages/account-abstraction-kit/src/types/index' 9 | 10 | // Fund the 1Balance account that will sponsor the transaction and get the API key: 11 | // https://relay.gelato.network/ 12 | 13 | // Check the status of a transaction after it is relayed: 14 | // https://relay.gelato.digital/tasks/status/ 15 | 16 | // Check the status of a transaction after it is executed: 17 | // https://goerli.etherscan.io/tx/ 18 | 19 | const config = { 20 | SAFE_SIGNER_PRIVATE_KEY: '', 21 | RPC_URL: 'https://goerli.infura.io/v3/', 22 | RELAY_API_KEY: '' 23 | } 24 | 25 | const mockOnRampConfig = { 26 | ADDRESS: '0x4D39a545144D8e2F19E8009aB5F123FA1043cc98', 27 | PRIVATE_KEY: '0x32ecaa3b2feb4051470c98b6d2f2da8861ae83b11ccc7123aee1c9efc4ef1933' 28 | } 29 | 30 | const txConfig = { 31 | TO: '', 32 | DATA: '', 33 | VALUE: BigNumber.from(''), 34 | // Options: 35 | GAS_LIMIT: BigNumber.from('') 36 | } 37 | 38 | async function main() { 39 | console.log('Execute meta-transaction via Gelato Relay paid by 1Balance') 40 | 41 | // SDK Initialization 42 | 43 | const provider = new ethers.providers.JsonRpcProvider(config.RPC_URL) 44 | const signer = new ethers.Wallet(config.SAFE_SIGNER_PRIVATE_KEY, provider) 45 | 46 | const relayAdapter = new GelatoRelayAdapter(config.RELAY_API_KEY) 47 | 48 | const safeAccountAbstraction = new AccountAbstraction(signer) 49 | const sdkConfig: AccountAbstractionConfig = { 50 | relayAdapter 51 | } 52 | await safeAccountAbstraction.init(sdkConfig) 53 | 54 | // Calculate Safe address 55 | 56 | const predictedSafeAddress = safeAccountAbstraction.getSafeAddress() 57 | console.log({ predictedSafeAddress }) 58 | 59 | const isSafeDeployed = await safeAccountAbstraction.isSafeDeployed() 60 | console.log({ isSafeDeployed }) 61 | 62 | // Fake on-ramp to fund the Safe 63 | 64 | const safeBalance = await provider.getBalance(predictedSafeAddress) 65 | console.log({ safeBalance: ethers.utils.formatEther(safeBalance.toString()) }) 66 | if (safeBalance.lt(txConfig.VALUE)) { 67 | const fakeOnRampSigner = new ethers.Wallet(mockOnRampConfig.PRIVATE_KEY, provider) 68 | const onRampResponse = await fakeOnRampSigner.sendTransaction({ 69 | to: predictedSafeAddress, 70 | value: txConfig.VALUE 71 | }) 72 | console.log( 73 | `Funding the Safe with ${ethers.utils.formatEther(txConfig.VALUE.toString())} ETH` 74 | ) 75 | await onRampResponse.wait() 76 | 77 | const safeBalanceAfter = await provider.getBalance(predictedSafeAddress) 78 | console.log({ safeBalance: ethers.utils.formatEther(safeBalanceAfter.toString()) }) 79 | } 80 | 81 | // Relay the transaction 82 | 83 | const safeTransaction: MetaTransactionData = { 84 | to: txConfig.TO, 85 | data: txConfig.DATA, 86 | value: txConfig.VALUE, 87 | operation: OperationType.Call 88 | } 89 | const options: MetaTransactionOptions = { 90 | gasLimit: txConfig.GAS_LIMIT, 91 | isSponsored: true 92 | } 93 | 94 | const response = await safeAccountAbstraction.relayTransaction(safeTransaction, options) 95 | console.log({ GelatoTaskId: response }) 96 | } 97 | 98 | main() 99 | -------------------------------------------------------------------------------- /packages/auth-kit/example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | import { SafeEventEmitterProvider } from '@web3auth/base' 3 | import { Box, Divider, Grid, Typography } from '@mui/material' 4 | import { EthHashInfo } from '@safe-global/safe-react-components' 5 | import { SafeAuthKit, SafeAuthProviderType, SafeAuthSignInData } from '../../src/index' 6 | 7 | import AppBar from './AppBar' 8 | 9 | function App() { 10 | const [safeAuthSignInResponse, setSafeAuthSignInResponse] = useState( 11 | null 12 | ) 13 | const [safeAuth, setSafeAuth] = useState() 14 | const [provider, setProvider] = useState(null) 15 | 16 | useEffect(() => { 17 | ;(async () => { 18 | setSafeAuth( 19 | await SafeAuthKit.init(SafeAuthProviderType.Web3Auth, { 20 | chainId: '0x5', 21 | txServiceUrl: 'https://safe-transaction-goerli.safe.global', // Optional. Only if want to retrieve related safes 22 | authProviderConfig: { 23 | rpcTarget: `https://goerli.infura.io/v3/${import.meta.env.VITE_INFURA_KEY}`, 24 | clientId: import.meta.env.VITE_WEB3AUTH_CLIENT_ID || '', 25 | network: 'testnet', 26 | theme: 'dark' 27 | } 28 | }) 29 | ) 30 | })() 31 | }, []) 32 | 33 | const login = async () => { 34 | if (!safeAuth) return 35 | 36 | const response = await safeAuth.signIn() 37 | console.log('SIGN IN RESPONSE: ', response) 38 | 39 | setSafeAuthSignInResponse(response) 40 | setProvider(safeAuth.getProvider() as SafeEventEmitterProvider) 41 | } 42 | 43 | const logout = async () => { 44 | if (!safeAuth) return 45 | 46 | await safeAuth.signOut() 47 | 48 | setProvider(null) 49 | setSafeAuthSignInResponse(null) 50 | } 51 | 52 | return ( 53 | <> 54 | 55 | {safeAuthSignInResponse?.eoa && ( 56 | 57 | 58 | 59 | Owner account 60 | 61 | 62 | 68 | 69 | 70 | <> 71 | 72 | Available Safes 73 | 74 | 75 | {safeAuthSignInResponse?.safes?.length ? ( 76 | safeAuthSignInResponse?.safes?.map((safe, index) => ( 77 | 78 | 79 | 80 | )) 81 | ) : ( 82 | 83 | No Available Safes 84 | 85 | )} 86 | 87 | 88 | 89 | )} 90 | 91 | ) 92 | } 93 | 94 | const getPrefix = (chainId: string) => { 95 | switch (chainId) { 96 | case '0x1': 97 | return 'eth' 98 | case '0x5': 99 | return 'gor' 100 | case '0x100': 101 | return 'gno' 102 | case '0x137': 103 | return 'matic' 104 | default: 105 | return 'eth' 106 | } 107 | } 108 | 109 | export default App 110 | -------------------------------------------------------------------------------- /playground/relay-kit/paid-transaction.ts: -------------------------------------------------------------------------------- 1 | import AccountAbstraction, { 2 | AccountAbstractionConfig, 3 | MetaTransactionData, 4 | MetaTransactionOptions, 5 | OperationType 6 | } from '@safe-global/account-abstraction-kit-poc' 7 | import { GelatoRelayAdapter } from '@safe-global/relay-kit' 8 | import { BigNumber, ethers } from 'ethers' 9 | 10 | // Check the status of a transaction after it is relayed: 11 | // https://relay.gelato.digital/tasks/status/ 12 | 13 | // Check the status of a transaction after it is executed: 14 | // https://goerli.etherscan.io/tx/ 15 | 16 | const config = { 17 | SAFE_SIGNER_PRIVATE_KEY: '', 18 | RPC_URL: 'https://goerli.infura.io/v3/' 19 | } 20 | 21 | const mockOnRampConfig = { 22 | ADDRESS: '
', 23 | PRIVATE_KEY: '' 24 | } 25 | 26 | const txConfig = { 27 | TO: '', 28 | DATA: '', 29 | VALUE: BigNumber.from(''), 30 | // Options: 31 | GAS_LIMIT: BigNumber.from(''), 32 | GAS_TOKEN: ethers.constants.AddressZero 33 | } 34 | 35 | async function main() { 36 | console.log('Execute meta-transaction via Gelato Relay paid with balance in the Safe') 37 | 38 | // SDK Initialization 39 | 40 | const provider = new ethers.providers.JsonRpcProvider(config.RPC_URL) 41 | const signer = new ethers.Wallet(config.SAFE_SIGNER_PRIVATE_KEY, provider) 42 | 43 | const relayAdapter = new GelatoRelayAdapter() 44 | 45 | const safeAccountAbstraction = new AccountAbstraction(signer) 46 | const sdkConfig: AccountAbstractionConfig = { 47 | relayAdapter 48 | } 49 | await safeAccountAbstraction.init(sdkConfig) 50 | 51 | // Calculate Safe address 52 | 53 | const predictedSafeAddress = safeAccountAbstraction.getSafeAddress() 54 | console.log({ predictedSafeAddress }) 55 | 56 | const isSafeDeployed = await safeAccountAbstraction.isSafeDeployed() 57 | console.log({ isSafeDeployed }) 58 | 59 | // Fake on-ramp to transfer enough funds to the Safe address 60 | 61 | const chainId = (await signer.provider.getNetwork()).chainId 62 | const relayFee = await relayAdapter.getEstimateFee( 63 | chainId, 64 | txConfig.GAS_LIMIT, 65 | txConfig.GAS_TOKEN 66 | ) 67 | const safeBalance = await provider.getBalance(predictedSafeAddress) 68 | console.log({ minSafeBalance: ethers.utils.formatEther(relayFee.toString()) }) 69 | console.log({ safeBalance: ethers.utils.formatEther(safeBalance.toString()) }) 70 | 71 | if (safeBalance.lt(relayFee)) { 72 | const fakeOnRampSigner = new ethers.Wallet(mockOnRampConfig.PRIVATE_KEY, provider) 73 | const fundingAmount = safeBalance.lt(relayFee) 74 | ? relayFee.sub(safeBalance) 75 | : safeBalance.sub(relayFee) 76 | const onRampResponse = await fakeOnRampSigner.sendTransaction({ 77 | to: predictedSafeAddress, 78 | value: fundingAmount 79 | }) 80 | console.log( 81 | `Funding the Safe with ${ethers.utils.formatEther(fundingAmount.toString())} ETH` 82 | ) 83 | await onRampResponse.wait() 84 | 85 | const safeBalanceAfter = await provider.getBalance(predictedSafeAddress) 86 | console.log({ safeBalance: ethers.utils.formatEther(safeBalanceAfter.toString()) }) 87 | } 88 | 89 | // Relay the transaction 90 | 91 | const safeTransaction: MetaTransactionData = { 92 | to: txConfig.TO, 93 | data: txConfig.DATA, 94 | value: txConfig.VALUE, 95 | operation: OperationType.Call 96 | } 97 | const options: MetaTransactionOptions = { 98 | gasLimit: txConfig.GAS_LIMIT, 99 | gasToken: txConfig.GAS_TOKEN 100 | } 101 | 102 | const response = await safeAccountAbstraction.relayTransaction(safeTransaction, options) 103 | console.log({ GelatoTaskId: response }) 104 | } 105 | 106 | main() 107 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/utils/contracts.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@ethersproject/bignumber' 2 | import { arrayify, BytesLike } from '@ethersproject/bytes' 3 | import { pack as solidityPack } from '@ethersproject/solidity' 4 | import { BigNumberish, ethers, Signer } from 'ethers' 5 | import { GnosisSafe } from '../../typechain/GnosisSafe' 6 | import { GnosisSafeProxyFactory } from '../../typechain/proxies/GnosisSafeProxyFactory' 7 | import { PREDETERMINED_SALT_NONCE, ZERO_ADDRESS } from '../constants' 8 | import { MetaTransactionData, SafeTransactionData } from '../types' 9 | import { 10 | getCompatibilityFallbackHandlerAddress, 11 | getSafeContract, 12 | getSafeProxyFactoryContract 13 | } from './deployments' 14 | 15 | export function encodeCreateProxyWithNonce( 16 | safeProxyFactoryContract: GnosisSafeProxyFactory, 17 | safeSingletonAddress: string, 18 | initializer: string 19 | ) { 20 | return safeProxyFactoryContract.interface.encodeFunctionData('createProxyWithNonce', [ 21 | safeSingletonAddress, 22 | initializer, 23 | PREDETERMINED_SALT_NONCE 24 | ]) 25 | } 26 | 27 | export function encodeSetupCallData( 28 | safeContract: GnosisSafe, 29 | owners: string[], 30 | chainId: number 31 | ): string { 32 | return safeContract.interface.encodeFunctionData('setup', [ 33 | owners, 34 | BigNumber.from(1) as BigNumberish, 35 | ZERO_ADDRESS, 36 | '0x' as BytesLike, 37 | getCompatibilityFallbackHandlerAddress(chainId), 38 | ZERO_ADDRESS, 39 | BigNumber.from(0) as BigNumberish, 40 | ZERO_ADDRESS 41 | ]) 42 | } 43 | 44 | export function encodeExecTransaction( 45 | safeContract: GnosisSafe, 46 | transaction: SafeTransactionData, 47 | signature: string 48 | ): string { 49 | return safeContract.interface.encodeFunctionData('execTransaction', [ 50 | transaction.to, 51 | transaction.value, 52 | transaction.data, 53 | transaction.operation, 54 | transaction.safeTxGas, 55 | transaction.baseGas, 56 | transaction.gasPrice, 57 | transaction.gasToken, 58 | transaction.refundReceiver, 59 | signature 60 | ]) 61 | } 62 | 63 | function encodeMetaTransaction(tx: MetaTransactionData): string { 64 | const data = arrayify(tx.data) 65 | const encoded = solidityPack( 66 | ['uint8', 'address', 'uint256', 'uint256', 'bytes'], 67 | [tx.operation, tx.to, tx.value, data.length, data] 68 | ) 69 | return encoded.slice(2) 70 | } 71 | 72 | export function encodeMultiSendData(txs: MetaTransactionData[]): string { 73 | return '0x' + txs.map((tx) => encodeMetaTransaction(tx)).join('') 74 | } 75 | 76 | export async function getSafeInitializer( 77 | safeContract: GnosisSafe, 78 | signerAddress: string, 79 | chainId: number 80 | ): Promise { 81 | const initializer = await encodeSetupCallData(safeContract, [signerAddress], chainId) 82 | return initializer 83 | } 84 | 85 | export async function calculateChainSpecificProxyAddress( 86 | safeProxyFactoryContract: GnosisSafeProxyFactory, 87 | signer: Signer, 88 | chainId: number 89 | ): Promise { 90 | const safeSingletonContract = getSafeContract(chainId, signer) 91 | const deployer = safeProxyFactoryContract.address 92 | const signerAddress = await signer.getAddress() 93 | 94 | const deploymentCode = ethers.utils.solidityPack( 95 | ['bytes', 'uint256'], 96 | [ 97 | await getSafeProxyFactoryContract(chainId, signer).proxyCreationCode(), 98 | safeSingletonContract.address 99 | ] 100 | ) 101 | const salt = ethers.utils.solidityKeccak256( 102 | ['bytes32', 'uint256'], 103 | [ 104 | ethers.utils.solidityKeccak256( 105 | ['bytes'], 106 | [await getSafeInitializer(safeSingletonContract, signerAddress, chainId)] 107 | ), 108 | PREDETERMINED_SALT_NONCE 109 | ] 110 | ) 111 | const derivedAddress = ethers.utils.getCreate2Address( 112 | deployer, 113 | salt, 114 | ethers.utils.keccak256(deploymentCode) 115 | ) 116 | return derivedAddress 117 | } 118 | -------------------------------------------------------------------------------- /packages/onramp-kit/src/adapters/stripe/StripeAdapter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SafeOnRampClient, 3 | StripeSession, 4 | SafeOnRampOpenOptions, 5 | StripeProviderConfig, 6 | SafeOnRampEventHandlers, 7 | SafeOnRampEvent, 8 | OnrampSessionUpdatedEvent 9 | } from '../../types' 10 | 11 | import * as stripeApi from './stripeApi' 12 | 13 | import { loadScript } from './utils' 14 | 15 | const STRIPE_JS_URL = 'https://js.stripe.com/v3/' 16 | const STRIPE_CRYPTO_JS_URL = 'https://crypto-js.stripe.com/crypto-onramp-outer.js' 17 | 18 | /** 19 | * This class implements the SafeOnRampClient interface for the Stripe provider 20 | * @class StripeAdapter 21 | */ 22 | export default class StripeAdapter implements SafeOnRampClient { 23 | #stripeOnRamp: any 24 | #onRampSession?: StripeSession 25 | #config: StripeProviderConfig 26 | #currentSessionOptions?: SafeOnRampOpenOptions 27 | 28 | /** 29 | * Initialize the StripeAdapter 30 | * @constructor 31 | * @param config The configuration object for the Stripe provider 32 | */ 33 | constructor(config: StripeProviderConfig) { 34 | this.#config = config 35 | } 36 | 37 | /** 38 | * This method loads the Stripe JS files and initializes the StripeOnRamp object 39 | */ 40 | async init() { 41 | try { 42 | await loadScript(STRIPE_JS_URL) 43 | await loadScript(STRIPE_CRYPTO_JS_URL) 44 | 45 | this.#stripeOnRamp = StripeOnramp(this.#config.stripePublicKey) 46 | } catch { 47 | throw new Error("Couldn't load Stripe's JS files") 48 | } 49 | } 50 | 51 | /** 52 | * This method open the onramp widget with the provided options 53 | * @param options The options to open the onramp widget 54 | */ 55 | async open(options: SafeOnRampOpenOptions) { 56 | try { 57 | let response 58 | 59 | if (options.sessionId) { 60 | response = await stripeApi.getSession(this.#config.onRampBackendUrl, options.sessionId) 61 | } else { 62 | response = await stripeApi.createSession(this.#config.onRampBackendUrl, { 63 | walletAddress: options.walletAddress, 64 | networks: options.networks 65 | }) 66 | } 67 | 68 | const data = await response.json() 69 | 70 | if (!response.ok) throw new Error() 71 | 72 | const onRampSession = await this.#stripeOnRamp.createSession({ 73 | clientSecret: data.client_secret 74 | }) 75 | 76 | this.#onRampSession = onRampSession 77 | this.#currentSessionOptions = options 78 | 79 | if (options.events) this.#bindEvents(options.events) 80 | 81 | onRampSession.mount(options.element) 82 | 83 | return data 84 | } catch { 85 | throw new Error('Error trying to create a new Stripe session') 86 | } 87 | } 88 | 89 | /** 90 | * This method close the onramp widget 91 | */ 92 | async close() { 93 | throw new Error('Method not implemented.') 94 | } 95 | 96 | /** 97 | * This method binds the event handlers to the onramp widget 98 | * @param events The event handlers to bind to the onramp widget 99 | */ 100 | #bindEvents(events: SafeOnRampEventHandlers) { 101 | this.#onRampSession?.addEventListener('onramp_ui_loaded', () => { 102 | events?.onLoaded?.() 103 | }) 104 | 105 | this.#onRampSession?.addEventListener( 106 | 'onramp_session_updated', 107 | (e: OnrampSessionUpdatedEvent) => { 108 | const safeEvent = this.stripeEventToSafeEvent(e) 109 | 110 | // TODO: Remove this check when not required 111 | // This is only in order to preserve testnets liquidity pools during the hackaton 112 | if (Number(e.payload.session.quote.source_monetary_amount?.replace(',', '.')) > 10) { 113 | document.querySelector(this.#currentSessionOptions?.element as string)?.remove() 114 | throw new Error( 115 | "The amount you are trying to use to complete your purchase can't be greater than 10 in order to preserve testnets liquidity pools" 116 | ) 117 | } 118 | 119 | if (e.payload.session.status === 'fulfillment_complete') { 120 | events?.onPaymentSuccessful?.(safeEvent) 121 | } 122 | 123 | if (e.payload.session.status === 'fulfillment_processing') { 124 | events?.onPaymentProcessing?.(safeEvent) 125 | } 126 | 127 | if (e.payload.session.status === 'rejected') { 128 | events?.onPaymentError?.(safeEvent) 129 | } 130 | } 131 | ) 132 | } 133 | 134 | private stripeEventToSafeEvent(stripeEvent: OnrampSessionUpdatedEvent): SafeOnRampEvent { 135 | const { session } = stripeEvent.payload 136 | const { quote } = session 137 | 138 | return { 139 | txId: quote.blockchain_tx_id, 140 | walletAddress: session.wallet_address, 141 | totalFee: quote.fees?.total_fee, 142 | totalAmount: quote.total_amount, 143 | destination: { 144 | asset: quote.destination_currency?.asset_code, 145 | amount: quote.destination_amount, 146 | network: quote.destination_currency?.currency_network 147 | }, 148 | source: { 149 | asset: quote.source_currency?.asset_code, 150 | amount: quote.source_amount, 151 | network: quote.source_currency?.currency_network 152 | } 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /packages/auth-kit/src/SafeAuthKit.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | import EventEmitter from 'events' 3 | import EthersAdapter from '@safe-global/safe-ethers-lib' 4 | import SafeServiceClient from '@safe-global/safe-service-client' 5 | import Web3AuthAdapter from './adapters/Web3AuthAdapter' 6 | 7 | import { 8 | SafeAuthClient, 9 | SafeAuthConfig, 10 | SafeAuthProviderType, 11 | SafeAuthSignInData, 12 | SafeAuthEvents 13 | } from './types' 14 | 15 | /** 16 | * SafeAuthKit provides a simple interface for web2 logins 17 | */ 18 | export default class SafeAuthKit extends EventEmitter { 19 | safeAuthData?: SafeAuthSignInData 20 | #client: SafeAuthClient 21 | #config: SafeAuthConfig 22 | 23 | /** 24 | * Initialize the SafeAuthKit 25 | * @constructor 26 | * @param client The client implementing the SafeAuthClient interface 27 | * @param config The configuration options 28 | */ 29 | constructor(client: SafeAuthClient, config: SafeAuthConfig) { 30 | super() 31 | 32 | this.#client = client 33 | this.#config = config 34 | } 35 | 36 | /** 37 | * The static method allows to initialize the SafeAuthKit asynchronously 38 | * @param providerType Choose the provider service to use 39 | * @param config The configuration including the one for the specific provider 40 | * @returns A SafeAuthKit instance 41 | * @throws Error if the provider type is not supported 42 | */ 43 | static async init( 44 | providerType: SafeAuthProviderType, 45 | config: SafeAuthConfig 46 | ): Promise { 47 | let client 48 | 49 | switch (providerType) { 50 | case SafeAuthProviderType.Web3Auth: 51 | client = new Web3AuthAdapter(config.chainId, config.authProviderConfig) 52 | break 53 | default: 54 | throw new Error('Provider type not supported') 55 | } 56 | 57 | await client.init() 58 | 59 | return new SafeAuthKit(client, config) 60 | } 61 | 62 | /** 63 | * Authenticate the user 64 | * @returns the derived external owned account and the safes associated with the user if the txServiceUrl is provided 65 | * @throws Error if the provider was not created 66 | * @throws Error if there was an error while trying to get the safes for the current user using the provided txServiceUrl 67 | */ 68 | async signIn(): Promise { 69 | await this.#client.signIn() 70 | 71 | if (!this.#client.provider) { 72 | throw new Error('Provider is not defined') 73 | } 74 | 75 | const ethersProvider = new ethers.providers.Web3Provider(this.#client.provider) 76 | const signer = ethersProvider.getSigner() 77 | const address = await signer.getAddress() 78 | 79 | let safes: string[] | undefined 80 | 81 | // Retrieve safes if txServiceUrl is provided 82 | if (this.#config.txServiceUrl) { 83 | try { 84 | const safesByOwner = await this.#getSafeCoreClient().getSafesByOwner(address) 85 | safes = safesByOwner.safes 86 | } catch (e) { 87 | throw new Error('There was an error while trying to get the safes for the current user') 88 | } 89 | } 90 | 91 | this.emit(SafeAuthEvents.SIGNED_IN) 92 | 93 | this.safeAuthData = { 94 | chainId: this.#config.chainId, 95 | eoa: address, 96 | safes 97 | } 98 | 99 | return this.safeAuthData 100 | } 101 | 102 | /** 103 | * Sign out the user 104 | */ 105 | async signOut(): Promise { 106 | await this.#client?.signOut() 107 | 108 | this.safeAuthData = undefined 109 | this.emit(SafeAuthEvents.SIGNED_OUT) 110 | } 111 | 112 | /** 113 | * 114 | * @returns The Ethereum provider 115 | */ 116 | getProvider() { 117 | if (!this.#client) return null 118 | 119 | return this.#client?.provider 120 | } 121 | 122 | /** 123 | * Subscribe to an event 124 | * @param eventName The event name to subscribe to. Choose from SafeAuthEvents type 125 | * @param listener The callback function to be called when the event is emitted 126 | */ 127 | subscribe(eventName: typeof SafeAuthEvents, listener: (...args: any[]) => void) { 128 | this.on(eventName.toString(), listener) 129 | } 130 | 131 | /** 132 | * Unsubscribe from an event 133 | * @param eventName The event name to unsubscribe from. Choose from SafeAuthEvents type 134 | * @param listener The callback function to unsubscribe 135 | */ 136 | unsubscribe(eventName: typeof SafeAuthEvents, listener: (...args: any[]) => void) { 137 | this.off(eventName.toString(), listener) 138 | } 139 | 140 | /** 141 | * Get the SafeServiceClient instance 142 | * @returns A SafeServiceClient instance 143 | */ 144 | #getSafeCoreClient(): SafeServiceClient { 145 | if (!this.#client?.provider) { 146 | throw new Error('Provider is not defined') 147 | } 148 | 149 | if (!this.#config.txServiceUrl) { 150 | throw new Error('txServiceUrl is not defined') 151 | } 152 | 153 | const provider = new ethers.providers.Web3Provider(this.#client?.provider) 154 | const safeOwner = provider.getSigner(0) 155 | 156 | const adapter = new EthersAdapter({ 157 | ethers, 158 | signerOrProvider: safeOwner 159 | }) 160 | 161 | return new SafeServiceClient({ 162 | txServiceUrl: this.#config.txServiceUrl, 163 | ethAdapter: adapter 164 | }) 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /packages/account-abstraction-kit/src/AccountAbstraction.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber, ethers } from 'ethers' 2 | import { GnosisSafe__factory } from '../typechain/factories' 3 | import { GnosisSafe } from '../typechain/GnosisSafe' 4 | import { MultiSendCallOnly } from '../typechain/libraries' 5 | import { GnosisSafeProxyFactory } from '../typechain/proxies' 6 | import { ZERO_ADDRESS } from './constants' 7 | import { 8 | AccountAbstractionConfig, 9 | MetaTransactionData, 10 | MetaTransactionOptions, 11 | OperationType, 12 | RelayAdapter, 13 | RelayTransaction, 14 | SafeTransactionData 15 | } from './types' 16 | import { getMultiSendCallOnlyContract, getSafeContract, getSafeProxyFactoryContract } from './utils' 17 | import { 18 | calculateChainSpecificProxyAddress, 19 | encodeCreateProxyWithNonce, 20 | encodeExecTransaction, 21 | encodeMultiSendData, 22 | getSafeInitializer 23 | } from './utils/contracts' 24 | import { getSignature } from './utils/signatures' 25 | 26 | class AccountAbstraction { 27 | #signer: ethers.Signer 28 | #chainId?: number 29 | #safeContract?: GnosisSafe 30 | #safeProxyFactoryContract?: GnosisSafeProxyFactory 31 | #multiSendCallOnlyContract?: MultiSendCallOnly 32 | #relayAdapter?: RelayAdapter 33 | 34 | constructor(signer: ethers.Signer) { 35 | this.#signer = signer 36 | } 37 | 38 | async init(options: AccountAbstractionConfig) { 39 | if (!this.#signer.provider) { 40 | throw new Error('Signer must be connected to a provider') 41 | } 42 | const { relayAdapter } = options 43 | this.setRelayAdapter(relayAdapter) 44 | 45 | this.#chainId = (await this.#signer.provider.getNetwork()).chainId 46 | this.#safeProxyFactoryContract = getSafeProxyFactoryContract(this.#chainId, this.#signer) 47 | this.#multiSendCallOnlyContract = getMultiSendCallOnlyContract(this.#chainId, this.#signer) 48 | const safeAddress = await calculateChainSpecificProxyAddress( 49 | this.#safeProxyFactoryContract, 50 | this.#signer, 51 | this.#chainId 52 | ) 53 | this.#safeContract = GnosisSafe__factory.connect(safeAddress, this.#signer) 54 | } 55 | 56 | setRelayAdapter(relayAdapter: RelayAdapter) { 57 | this.#relayAdapter = relayAdapter 58 | } 59 | 60 | async getSignerAddress(): Promise { 61 | const signerAddress = await this.#signer.getAddress() 62 | return signerAddress 63 | } 64 | 65 | async getNonce(): Promise { 66 | if (!this.#safeContract) { 67 | throw new Error('SDK not initialized') 68 | } 69 | return (await this.isSafeDeployed()) ? (await this.#safeContract.nonce()).toNumber() : 0 70 | } 71 | 72 | getSafeAddress(): string { 73 | if (!this.#safeContract) { 74 | throw new Error('SDK not initialized') 75 | } 76 | return this.#safeContract.address 77 | } 78 | 79 | async isSafeDeployed(): Promise { 80 | if (!this.#signer.provider) { 81 | throw new Error('SDK not initialized') 82 | } 83 | const address = this.getSafeAddress() 84 | const codeAtAddress = await this.#signer.provider.getCode(address) 85 | const isDeployed = codeAtAddress !== '0x' 86 | return isDeployed 87 | } 88 | 89 | private async _standardizeSafeTransactionData( 90 | transaction: MetaTransactionData, 91 | options: MetaTransactionOptions 92 | ): Promise { 93 | if (!this.#relayAdapter || !this.#chainId) { 94 | throw new Error('SDK not initialized') 95 | } 96 | const { gasLimit, gasToken, isSponsored } = options 97 | const estimation = await this.#relayAdapter.getEstimateFee(this.#chainId, gasLimit, gasToken) 98 | 99 | const standardizedSafeTx: SafeTransactionData = { 100 | to: transaction.to, 101 | value: transaction.value, 102 | data: transaction.data, 103 | operation: transaction.operation ?? OperationType.Call, 104 | safeTxGas: BigNumber.from(0), // Only Safe v1.3.0 supported so far 105 | baseGas: !isSponsored ? estimation : BigNumber.from(0), 106 | gasPrice: !isSponsored ? BigNumber.from(1) : BigNumber.from(0), 107 | gasToken: gasToken ?? ZERO_ADDRESS, 108 | refundReceiver: !isSponsored ? this.#relayAdapter.getFeeCollector() : ZERO_ADDRESS, 109 | nonce: await this.getNonce() 110 | } 111 | return standardizedSafeTx 112 | } 113 | 114 | async relayTransaction( 115 | transaction: MetaTransactionData, 116 | options: MetaTransactionOptions 117 | ): Promise { 118 | if ( 119 | !this.#relayAdapter || 120 | !this.#chainId || 121 | !this.#safeContract || 122 | !this.#multiSendCallOnlyContract || 123 | !this.#safeProxyFactoryContract 124 | ) { 125 | throw new Error('SDK not initialized') 126 | } 127 | 128 | const standardizedSafeTx = await this._standardizeSafeTransactionData(transaction, options) 129 | const signature = await getSignature( 130 | this.#signer, 131 | this.getSafeAddress(), 132 | standardizedSafeTx, 133 | this.#chainId 134 | ) 135 | const transactionData = await encodeExecTransaction( 136 | this.#safeContract, 137 | standardizedSafeTx, 138 | signature 139 | ) 140 | 141 | let relayTransactionTarget = '' 142 | let encodedTransaction = '' 143 | const isSafeDeployed = await this.isSafeDeployed() 144 | if (isSafeDeployed) { 145 | relayTransactionTarget = this.#safeContract.address 146 | encodedTransaction = transactionData 147 | } else { 148 | relayTransactionTarget = this.#multiSendCallOnlyContract.address 149 | const safeSingletonContract = getSafeContract(this.#chainId, this.#signer) 150 | const initializer = await getSafeInitializer( 151 | this.#safeContract, 152 | await this.getSignerAddress(), 153 | this.#chainId 154 | ) 155 | 156 | const safeDeploymentTransaction: MetaTransactionData = { 157 | to: this.#safeProxyFactoryContract.address, 158 | value: BigNumber.from(0), 159 | data: encodeCreateProxyWithNonce( 160 | this.#safeProxyFactoryContract, 161 | safeSingletonContract.address, 162 | initializer 163 | ), 164 | operation: OperationType.Call 165 | } 166 | const safeTransaction: MetaTransactionData = { 167 | to: this.#safeContract.address, 168 | value: BigNumber.from(0), 169 | data: transactionData, 170 | operation: OperationType.Call 171 | } 172 | 173 | const multiSendData = encodeMultiSendData([safeDeploymentTransaction, safeTransaction]) 174 | encodedTransaction = this.#multiSendCallOnlyContract.interface.encodeFunctionData( 175 | 'multiSend', 176 | [multiSendData] 177 | ) 178 | } 179 | 180 | const relayTransaction: RelayTransaction = { 181 | target: relayTransactionTarget, 182 | encodedTransaction: encodedTransaction, 183 | chainId: this.#chainId, 184 | options 185 | } 186 | const response = await this.#relayAdapter.relayTransaction(relayTransaction) 187 | return response.taskId 188 | } 189 | } 190 | 191 | export default AccountAbstraction 192 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | "moduleResolution": "node16", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | "baseUrl": ".", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | "outDir": "./build", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | "noEmit": false, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | }, 103 | } 104 | -------------------------------------------------------------------------------- /packages/onramp-kit/example/server/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@cspotcode/source-map-support@^0.8.0": 6 | version "0.8.1" 7 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" 8 | integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== 9 | dependencies: 10 | "@jridgewell/trace-mapping" "0.3.9" 11 | 12 | "@jridgewell/resolve-uri@^3.0.3": 13 | version "3.1.0" 14 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" 15 | integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== 16 | 17 | "@jridgewell/sourcemap-codec@^1.4.10": 18 | version "1.4.14" 19 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" 20 | integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== 21 | 22 | "@jridgewell/trace-mapping@0.3.9": 23 | version "0.3.9" 24 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" 25 | integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== 26 | dependencies: 27 | "@jridgewell/resolve-uri" "^3.0.3" 28 | "@jridgewell/sourcemap-codec" "^1.4.10" 29 | 30 | "@tsconfig/node10@^1.0.7": 31 | version "1.0.9" 32 | resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" 33 | integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== 34 | 35 | "@tsconfig/node12@^1.0.7": 36 | version "1.0.11" 37 | resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" 38 | integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== 39 | 40 | "@tsconfig/node14@^1.0.0": 41 | version "1.0.3" 42 | resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" 43 | integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== 44 | 45 | "@tsconfig/node16@^1.0.2": 46 | version "1.0.3" 47 | resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" 48 | integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== 49 | 50 | "@types/body-parser@*": 51 | version "1.19.2" 52 | resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" 53 | integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== 54 | dependencies: 55 | "@types/connect" "*" 56 | "@types/node" "*" 57 | 58 | "@types/connect@*": 59 | version "3.4.35" 60 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" 61 | integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== 62 | dependencies: 63 | "@types/node" "*" 64 | 65 | "@types/cors@^2.8.13": 66 | version "2.8.13" 67 | resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.13.tgz#b8ade22ba455a1b8cb3b5d3f35910fd204f84f94" 68 | integrity sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA== 69 | dependencies: 70 | "@types/node" "*" 71 | 72 | "@types/express-serve-static-core@^4.17.33": 73 | version "4.17.33" 74 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" 75 | integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== 76 | dependencies: 77 | "@types/node" "*" 78 | "@types/qs" "*" 79 | "@types/range-parser" "*" 80 | 81 | "@types/express@^4.17.17": 82 | version "4.17.17" 83 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" 84 | integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== 85 | dependencies: 86 | "@types/body-parser" "*" 87 | "@types/express-serve-static-core" "^4.17.33" 88 | "@types/qs" "*" 89 | "@types/serve-static" "*" 90 | 91 | "@types/mime@*": 92 | version "3.0.1" 93 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" 94 | integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== 95 | 96 | "@types/node@*", "@types/node@^18.13.0": 97 | version "18.13.0" 98 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850" 99 | integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg== 100 | 101 | "@types/qs@*": 102 | version "6.9.7" 103 | resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" 104 | integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== 105 | 106 | "@types/range-parser@*": 107 | version "1.2.4" 108 | resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" 109 | integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== 110 | 111 | "@types/serve-static@*": 112 | version "1.15.0" 113 | resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" 114 | integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== 115 | dependencies: 116 | "@types/mime" "*" 117 | "@types/node" "*" 118 | 119 | abbrev@1: 120 | version "1.1.1" 121 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" 122 | integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== 123 | 124 | abort-controller@^3.0.0: 125 | version "3.0.0" 126 | resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" 127 | integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== 128 | dependencies: 129 | event-target-shim "^5.0.0" 130 | 131 | accepts@~1.3.8: 132 | version "1.3.8" 133 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 134 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 135 | dependencies: 136 | mime-types "~2.1.34" 137 | negotiator "0.6.3" 138 | 139 | acorn-walk@^8.1.1: 140 | version "8.2.0" 141 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" 142 | integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== 143 | 144 | acorn@^8.4.1: 145 | version "8.8.2" 146 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" 147 | integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== 148 | 149 | anymatch@~3.1.2: 150 | version "3.1.3" 151 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 152 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 153 | dependencies: 154 | normalize-path "^3.0.0" 155 | picomatch "^2.0.4" 156 | 157 | arg@^4.1.0: 158 | version "4.1.3" 159 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" 160 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 161 | 162 | array-flatten@1.1.1: 163 | version "1.1.1" 164 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 165 | integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== 166 | 167 | async@^2.6.4: 168 | version "2.6.4" 169 | resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" 170 | integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== 171 | dependencies: 172 | lodash "^4.17.14" 173 | 174 | asynckit@^0.4.0: 175 | version "0.4.0" 176 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 177 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 178 | 179 | atomic-sleep@^1.0.0: 180 | version "1.0.0" 181 | resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" 182 | integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== 183 | 184 | axios@^1.3.3: 185 | version "1.3.3" 186 | resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.3.tgz#e7011384ba839b885007c9c9fae1ff23dceb295b" 187 | integrity sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA== 188 | dependencies: 189 | follow-redirects "^1.15.0" 190 | form-data "^4.0.0" 191 | proxy-from-env "^1.1.0" 192 | 193 | balanced-match@^1.0.0: 194 | version "1.0.2" 195 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 196 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 197 | 198 | base64-js@^1.3.1: 199 | version "1.5.1" 200 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 201 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 202 | 203 | binary-extensions@^2.0.0: 204 | version "2.2.0" 205 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 206 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 207 | 208 | body-parser@1.20.1: 209 | version "1.20.1" 210 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" 211 | integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== 212 | dependencies: 213 | bytes "3.1.2" 214 | content-type "~1.0.4" 215 | debug "2.6.9" 216 | depd "2.0.0" 217 | destroy "1.2.0" 218 | http-errors "2.0.0" 219 | iconv-lite "0.4.24" 220 | on-finished "2.4.1" 221 | qs "6.11.0" 222 | raw-body "2.5.1" 223 | type-is "~1.6.18" 224 | unpipe "1.0.0" 225 | 226 | brace-expansion@^1.1.7: 227 | version "1.1.11" 228 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 229 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 230 | dependencies: 231 | balanced-match "^1.0.0" 232 | concat-map "0.0.1" 233 | 234 | brace-expansion@^2.0.1: 235 | version "2.0.1" 236 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 237 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 238 | dependencies: 239 | balanced-match "^1.0.0" 240 | 241 | braces@~3.0.2: 242 | version "3.0.2" 243 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 244 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 245 | dependencies: 246 | fill-range "^7.0.1" 247 | 248 | buffer@^6.0.3: 249 | version "6.0.3" 250 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" 251 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 252 | dependencies: 253 | base64-js "^1.3.1" 254 | ieee754 "^1.2.1" 255 | 256 | bytes@3.1.2: 257 | version "3.1.2" 258 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 259 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 260 | 261 | call-bind@^1.0.0: 262 | version "1.0.2" 263 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 264 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 265 | dependencies: 266 | function-bind "^1.1.1" 267 | get-intrinsic "^1.0.2" 268 | 269 | caller@^1.0.0: 270 | version "1.1.0" 271 | resolved "https://registry.yarnpkg.com/caller/-/caller-1.1.0.tgz#46228555cfecb57d82bcd173b493f87cee9680fe" 272 | integrity sha512-n+21IZC3j06YpCWaxmUy5AnVqhmCIM2bQtqQyy00HJlmStRt6kwDX5F9Z97pqwAB+G/tgSz6q/kUBbNyQzIubw== 273 | 274 | chokidar@^3.5.2: 275 | version "3.5.3" 276 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 277 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 278 | dependencies: 279 | anymatch "~3.1.2" 280 | braces "~3.0.2" 281 | glob-parent "~5.1.2" 282 | is-binary-path "~2.1.0" 283 | is-glob "~4.0.1" 284 | normalize-path "~3.0.0" 285 | readdirp "~3.6.0" 286 | optionalDependencies: 287 | fsevents "~2.3.2" 288 | 289 | colorette@^2.0.7: 290 | version "2.0.19" 291 | resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" 292 | integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== 293 | 294 | colors@1.0.x: 295 | version "1.0.3" 296 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" 297 | integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw== 298 | 299 | combined-stream@^1.0.8: 300 | version "1.0.8" 301 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 302 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 303 | dependencies: 304 | delayed-stream "~1.0.0" 305 | 306 | concat-map@0.0.1: 307 | version "0.0.1" 308 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 309 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 310 | 311 | content-disposition@0.5.4: 312 | version "0.5.4" 313 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 314 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 315 | dependencies: 316 | safe-buffer "5.2.1" 317 | 318 | content-type@~1.0.4: 319 | version "1.0.5" 320 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 321 | integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 322 | 323 | cookie-signature@1.0.6: 324 | version "1.0.6" 325 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 326 | integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== 327 | 328 | cookie@0.5.0: 329 | version "0.5.0" 330 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" 331 | integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 332 | 333 | cors@^2.8.5: 334 | version "2.8.5" 335 | resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" 336 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== 337 | dependencies: 338 | object-assign "^4" 339 | vary "^1" 340 | 341 | create-require@^1.1.0: 342 | version "1.1.1" 343 | resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" 344 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 345 | 346 | cycle@1.0.x: 347 | version "1.0.3" 348 | resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" 349 | integrity sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA== 350 | 351 | dateformat@^4.6.3: 352 | version "4.6.3" 353 | resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" 354 | integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== 355 | 356 | debug@2.6.9: 357 | version "2.6.9" 358 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 359 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 360 | dependencies: 361 | ms "2.0.0" 362 | 363 | debug@^3.2.7: 364 | version "3.2.7" 365 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" 366 | integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== 367 | dependencies: 368 | ms "^2.1.1" 369 | 370 | delayed-stream@~1.0.0: 371 | version "1.0.0" 372 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 373 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 374 | 375 | depd@2.0.0: 376 | version "2.0.0" 377 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 378 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 379 | 380 | destroy@1.2.0: 381 | version "1.2.0" 382 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 383 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 384 | 385 | diff@^4.0.1: 386 | version "4.0.2" 387 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 388 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 389 | 390 | dotenv@^16.0.3: 391 | version "16.0.3" 392 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" 393 | integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== 394 | 395 | ee-first@1.1.1: 396 | version "1.1.1" 397 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 398 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 399 | 400 | encodeurl@~1.0.2: 401 | version "1.0.2" 402 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 403 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 404 | 405 | end-of-stream@^1.1.0: 406 | version "1.4.4" 407 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 408 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 409 | dependencies: 410 | once "^1.4.0" 411 | 412 | escape-html@~1.0.3: 413 | version "1.0.3" 414 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 415 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 416 | 417 | etag@~1.8.1: 418 | version "1.8.1" 419 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 420 | integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 421 | 422 | event-target-shim@^5.0.0: 423 | version "5.0.1" 424 | resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" 425 | integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== 426 | 427 | events@^3.3.0: 428 | version "3.3.0" 429 | resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" 430 | integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== 431 | 432 | express@^4.18.2: 433 | version "4.18.2" 434 | resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" 435 | integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== 436 | dependencies: 437 | accepts "~1.3.8" 438 | array-flatten "1.1.1" 439 | body-parser "1.20.1" 440 | content-disposition "0.5.4" 441 | content-type "~1.0.4" 442 | cookie "0.5.0" 443 | cookie-signature "1.0.6" 444 | debug "2.6.9" 445 | depd "2.0.0" 446 | encodeurl "~1.0.2" 447 | escape-html "~1.0.3" 448 | etag "~1.8.1" 449 | finalhandler "1.2.0" 450 | fresh "0.5.2" 451 | http-errors "2.0.0" 452 | merge-descriptors "1.0.1" 453 | methods "~1.1.2" 454 | on-finished "2.4.1" 455 | parseurl "~1.3.3" 456 | path-to-regexp "0.1.7" 457 | proxy-addr "~2.0.7" 458 | qs "6.11.0" 459 | range-parser "~1.2.1" 460 | safe-buffer "5.2.1" 461 | send "0.18.0" 462 | serve-static "1.15.0" 463 | setprototypeof "1.2.0" 464 | statuses "2.0.1" 465 | type-is "~1.6.18" 466 | utils-merge "1.0.1" 467 | vary "~1.1.2" 468 | 469 | eyes@0.1.x: 470 | version "0.1.8" 471 | resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" 472 | integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== 473 | 474 | fast-copy@^3.0.0: 475 | version "3.0.0" 476 | resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.0.tgz#875ebf33b13948ae012b6e51d33da5e6e7571ab8" 477 | integrity sha512-4HzS+9pQ5Yxtv13Lhs1Z1unMXamBdn5nA4bEi1abYpDNSpSp7ODYQ1KPMF6nTatfEzgH6/zPvXKU1zvHiUjWlA== 478 | 479 | fast-redact@^3.1.1: 480 | version "3.1.2" 481 | resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa" 482 | integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw== 483 | 484 | fast-safe-stringify@^2.1.1: 485 | version "2.1.1" 486 | resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" 487 | integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== 488 | 489 | fill-range@^7.0.1: 490 | version "7.0.1" 491 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 492 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 493 | dependencies: 494 | to-regex-range "^5.0.1" 495 | 496 | finalhandler@1.2.0: 497 | version "1.2.0" 498 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" 499 | integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 500 | dependencies: 501 | debug "2.6.9" 502 | encodeurl "~1.0.2" 503 | escape-html "~1.0.3" 504 | on-finished "2.4.1" 505 | parseurl "~1.3.3" 506 | statuses "2.0.1" 507 | unpipe "~1.0.0" 508 | 509 | follow-redirects@^1.15.0: 510 | version "1.15.2" 511 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" 512 | integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== 513 | 514 | form-data@^4.0.0: 515 | version "4.0.0" 516 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" 517 | integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== 518 | dependencies: 519 | asynckit "^0.4.0" 520 | combined-stream "^1.0.8" 521 | mime-types "^2.1.12" 522 | 523 | forwarded@0.2.0: 524 | version "0.2.0" 525 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 526 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 527 | 528 | fresh@0.5.2: 529 | version "0.5.2" 530 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 531 | integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 532 | 533 | fs.realpath@^1.0.0: 534 | version "1.0.0" 535 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 536 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 537 | 538 | fsevents@~2.3.2: 539 | version "2.3.2" 540 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 541 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 542 | 543 | function-bind@^1.1.1: 544 | version "1.1.1" 545 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 546 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 547 | 548 | get-caller-file@^2.0.5: 549 | version "2.0.5" 550 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 551 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 552 | 553 | get-intrinsic@^1.0.2: 554 | version "1.2.0" 555 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" 556 | integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== 557 | dependencies: 558 | function-bind "^1.1.1" 559 | has "^1.0.3" 560 | has-symbols "^1.0.3" 561 | 562 | glob-parent@~5.1.2: 563 | version "5.1.2" 564 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 565 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 566 | dependencies: 567 | is-glob "^4.0.1" 568 | 569 | glob@^8.0.0: 570 | version "8.1.0" 571 | resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" 572 | integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== 573 | dependencies: 574 | fs.realpath "^1.0.0" 575 | inflight "^1.0.4" 576 | inherits "2" 577 | minimatch "^5.0.1" 578 | once "^1.3.0" 579 | 580 | has-flag@^3.0.0: 581 | version "3.0.0" 582 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 583 | integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== 584 | 585 | has-symbols@^1.0.3: 586 | version "1.0.3" 587 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 588 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 589 | 590 | has@^1.0.3: 591 | version "1.0.3" 592 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 593 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 594 | dependencies: 595 | function-bind "^1.1.1" 596 | 597 | help-me@^4.0.1: 598 | version "4.2.0" 599 | resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.2.0.tgz#50712bfd799ff1854ae1d312c36eafcea85b0563" 600 | integrity sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA== 601 | dependencies: 602 | glob "^8.0.0" 603 | readable-stream "^3.6.0" 604 | 605 | http-errors@2.0.0: 606 | version "2.0.0" 607 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 608 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 609 | dependencies: 610 | depd "2.0.0" 611 | inherits "2.0.4" 612 | setprototypeof "1.2.0" 613 | statuses "2.0.1" 614 | toidentifier "1.0.1" 615 | 616 | iconv-lite@0.4.24: 617 | version "0.4.24" 618 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 619 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 620 | dependencies: 621 | safer-buffer ">= 2.1.2 < 3" 622 | 623 | ieee754@^1.2.1: 624 | version "1.2.1" 625 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 626 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 627 | 628 | ignore-by-default@^1.0.1: 629 | version "1.0.1" 630 | resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" 631 | integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== 632 | 633 | inflight@^1.0.4: 634 | version "1.0.6" 635 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 636 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 637 | dependencies: 638 | once "^1.3.0" 639 | wrappy "1" 640 | 641 | inherits@2, inherits@2.0.4, inherits@^2.0.3: 642 | version "2.0.4" 643 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 644 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 645 | 646 | ipaddr.js@1.9.1: 647 | version "1.9.1" 648 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 649 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 650 | 651 | is-binary-path@~2.1.0: 652 | version "2.1.0" 653 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 654 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 655 | dependencies: 656 | binary-extensions "^2.0.0" 657 | 658 | is-extglob@^2.1.1: 659 | version "2.1.1" 660 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 661 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 662 | 663 | is-glob@^4.0.1, is-glob@~4.0.1: 664 | version "4.0.3" 665 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 666 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 667 | dependencies: 668 | is-extglob "^2.1.1" 669 | 670 | is-number@^7.0.0: 671 | version "7.0.0" 672 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 673 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 674 | 675 | isstream@0.1.x: 676 | version "0.1.2" 677 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 678 | integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== 679 | 680 | joycon@^3.1.1: 681 | version "3.1.1" 682 | resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" 683 | integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== 684 | 685 | lodash-node@^2.4.1: 686 | version "2.4.1" 687 | resolved "https://registry.yarnpkg.com/lodash-node/-/lodash-node-2.4.1.tgz#ea82f7b100c733d1a42af76801e506105e2a80ec" 688 | integrity sha512-egEt8eNQp2kZWRmngahiqMoDCDCENv3uM188S7Ed5t4k3v6RrLELXC+FqLNMUnhCo7gvQX3G1V8opK/Lcslahg== 689 | 690 | lodash@^4.17.14: 691 | version "4.17.21" 692 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 693 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 694 | 695 | make-error@^1.1.1: 696 | version "1.3.6" 697 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 698 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 699 | 700 | media-typer@0.3.0: 701 | version "0.3.0" 702 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 703 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 704 | 705 | merge-descriptors@1.0.1: 706 | version "1.0.1" 707 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 708 | integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== 709 | 710 | methods@~1.1.2: 711 | version "1.1.2" 712 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 713 | integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== 714 | 715 | mime-db@1.52.0: 716 | version "1.52.0" 717 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 718 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 719 | 720 | mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: 721 | version "2.1.35" 722 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 723 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 724 | dependencies: 725 | mime-db "1.52.0" 726 | 727 | mime@1.6.0: 728 | version "1.6.0" 729 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 730 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 731 | 732 | minimatch@^3.1.2: 733 | version "3.1.2" 734 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 735 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 736 | dependencies: 737 | brace-expansion "^1.1.7" 738 | 739 | minimatch@^5.0.1: 740 | version "5.1.6" 741 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" 742 | integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== 743 | dependencies: 744 | brace-expansion "^2.0.1" 745 | 746 | minimist@^1.2.6: 747 | version "1.2.8" 748 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 749 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 750 | 751 | ms@2.0.0: 752 | version "2.0.0" 753 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 754 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 755 | 756 | ms@2.1.3, ms@^2.1.1: 757 | version "2.1.3" 758 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 759 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 760 | 761 | negotiator@0.6.3: 762 | version "0.6.3" 763 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 764 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 765 | 766 | nodemon@^2.0.20: 767 | version "2.0.20" 768 | resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.20.tgz#e3537de768a492e8d74da5c5813cb0c7486fc701" 769 | integrity sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw== 770 | dependencies: 771 | chokidar "^3.5.2" 772 | debug "^3.2.7" 773 | ignore-by-default "^1.0.1" 774 | minimatch "^3.1.2" 775 | pstree.remy "^1.1.8" 776 | semver "^5.7.1" 777 | simple-update-notifier "^1.0.7" 778 | supports-color "^5.5.0" 779 | touch "^3.1.0" 780 | undefsafe "^2.0.5" 781 | 782 | nopt@~1.0.10: 783 | version "1.0.10" 784 | resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" 785 | integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== 786 | dependencies: 787 | abbrev "1" 788 | 789 | normalize-path@^3.0.0, normalize-path@~3.0.0: 790 | version "3.0.0" 791 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 792 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 793 | 794 | object-assign@^4: 795 | version "4.1.1" 796 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 797 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 798 | 799 | object-inspect@^1.9.0: 800 | version "1.12.3" 801 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" 802 | integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== 803 | 804 | on-exit-leak-free@^2.1.0: 805 | version "2.1.0" 806 | resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" 807 | integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w== 808 | 809 | on-finished@2.4.1: 810 | version "2.4.1" 811 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 812 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 813 | dependencies: 814 | ee-first "1.1.1" 815 | 816 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 817 | version "1.4.0" 818 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 819 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 820 | dependencies: 821 | wrappy "1" 822 | 823 | parseurl@~1.3.3: 824 | version "1.3.3" 825 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 826 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 827 | 828 | path-to-regexp@0.1.7: 829 | version "0.1.7" 830 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 831 | integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== 832 | 833 | picomatch@^2.0.4, picomatch@^2.2.1: 834 | version "2.3.1" 835 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 836 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 837 | 838 | pine@^1.1.1: 839 | version "1.1.1" 840 | resolved "https://registry.yarnpkg.com/pine/-/pine-1.1.1.tgz#4a74df92601096a8608742bc4b792c9d680eb865" 841 | integrity sha512-Xk+dW+1oCpPVjNgzg0PPrHamc7aCj9LM37Qwp8pxraWIW1JFlYExr3CBXEl0ghBG2L2cCcFp8JHPDC55Dv+7iw== 842 | dependencies: 843 | caller "^1.0.0" 844 | lodash-node "^2.4.1" 845 | winston "^2.2.0" 846 | 847 | pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0: 848 | version "1.0.0" 849 | resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" 850 | integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA== 851 | dependencies: 852 | readable-stream "^4.0.0" 853 | split2 "^4.0.0" 854 | 855 | pino-http@^8.3.3: 856 | version "8.3.3" 857 | resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-8.3.3.tgz#2b140e734bfc6babe0df272a43bb8f36f2b525c0" 858 | integrity sha512-p4umsNIXXVu95HD2C8wie/vXH7db5iGRpc+yj1/ZQ3sRtTQLXNjoS6Be5+eI+rQbqCRxen/7k/KSN+qiZubGDw== 859 | dependencies: 860 | get-caller-file "^2.0.5" 861 | pino "^8.0.0" 862 | pino-std-serializers "^6.0.0" 863 | process-warning "^2.0.0" 864 | 865 | pino-pretty@^9.2.0: 866 | version "9.2.0" 867 | resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-9.2.0.tgz#4a6bcc677533f4053acd841bd9ccc9be9122c8af" 868 | integrity sha512-7CeszmFqrUD08+JvtYcFXowNE7duFlE1XScmR41qTMbwQOhn7gijYYrRb5udH+z8xq4+A8vN8rQNYVPCTfzmGw== 869 | dependencies: 870 | colorette "^2.0.7" 871 | dateformat "^4.6.3" 872 | fast-copy "^3.0.0" 873 | fast-safe-stringify "^2.1.1" 874 | help-me "^4.0.1" 875 | joycon "^3.1.1" 876 | minimist "^1.2.6" 877 | on-exit-leak-free "^2.1.0" 878 | pino-abstract-transport "^1.0.0" 879 | pump "^3.0.0" 880 | readable-stream "^4.0.0" 881 | secure-json-parse "^2.4.0" 882 | sonic-boom "^3.0.0" 883 | strip-json-comments "^3.1.1" 884 | 885 | pino-std-serializers@^6.0.0: 886 | version "6.1.0" 887 | resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.1.0.tgz#307490fd426eefc95e06067e85d8558603e8e844" 888 | integrity sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g== 889 | 890 | pino@^8.0.0: 891 | version "8.10.0" 892 | resolved "https://registry.yarnpkg.com/pino/-/pino-8.10.0.tgz#fe35a3fe90554630b0254d3f810f6fae27c38990" 893 | integrity sha512-ODfIe+giJtQGsvNAEj5/sHHpL3TFBg161JBH4W62Hc0l0PJjsDFD1R7meLI4PZ2aoHDJznxFNShkJcaG/qJToQ== 894 | dependencies: 895 | atomic-sleep "^1.0.0" 896 | fast-redact "^3.1.1" 897 | on-exit-leak-free "^2.1.0" 898 | pino-abstract-transport v1.0.0 899 | pino-std-serializers "^6.0.0" 900 | process-warning "^2.0.0" 901 | quick-format-unescaped "^4.0.3" 902 | real-require "^0.2.0" 903 | safe-stable-stringify "^2.3.1" 904 | sonic-boom "^3.1.0" 905 | thread-stream "^2.0.0" 906 | 907 | process-warning@^2.0.0: 908 | version "2.1.0" 909 | resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.1.0.tgz#1e60e3bfe8183033bbc1e702c2da74f099422d1a" 910 | integrity sha512-9C20RLxrZU/rFnxWncDkuF6O999NdIf3E1ws4B0ZeY3sRVPzWBMsYDE2lxjxhiXxg464cQTgKUGm8/i6y2YGXg== 911 | 912 | process@^0.11.10: 913 | version "0.11.10" 914 | resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" 915 | integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== 916 | 917 | proxy-addr@~2.0.7: 918 | version "2.0.7" 919 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 920 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 921 | dependencies: 922 | forwarded "0.2.0" 923 | ipaddr.js "1.9.1" 924 | 925 | proxy-from-env@^1.1.0: 926 | version "1.1.0" 927 | resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" 928 | integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== 929 | 930 | pstree.remy@^1.1.8: 931 | version "1.1.8" 932 | resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" 933 | integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== 934 | 935 | pump@^3.0.0: 936 | version "3.0.0" 937 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 938 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 939 | dependencies: 940 | end-of-stream "^1.1.0" 941 | once "^1.3.1" 942 | 943 | qs@6.11.0: 944 | version "6.11.0" 945 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 946 | integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 947 | dependencies: 948 | side-channel "^1.0.4" 949 | 950 | quick-format-unescaped@^4.0.3: 951 | version "4.0.4" 952 | resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" 953 | integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== 954 | 955 | range-parser@~1.2.1: 956 | version "1.2.1" 957 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 958 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 959 | 960 | raw-body@2.5.1: 961 | version "2.5.1" 962 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 963 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 964 | dependencies: 965 | bytes "3.1.2" 966 | http-errors "2.0.0" 967 | iconv-lite "0.4.24" 968 | unpipe "1.0.0" 969 | 970 | readable-stream@^3.6.0: 971 | version "3.6.0" 972 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" 973 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== 974 | dependencies: 975 | inherits "^2.0.3" 976 | string_decoder "^1.1.1" 977 | util-deprecate "^1.0.1" 978 | 979 | readable-stream@^4.0.0: 980 | version "4.3.0" 981 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.3.0.tgz#0914d0c72db03b316c9733bb3461d64a3cc50cba" 982 | integrity sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ== 983 | dependencies: 984 | abort-controller "^3.0.0" 985 | buffer "^6.0.3" 986 | events "^3.3.0" 987 | process "^0.11.10" 988 | 989 | readdirp@~3.6.0: 990 | version "3.6.0" 991 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 992 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 993 | dependencies: 994 | picomatch "^2.2.1" 995 | 996 | real-require@^0.2.0: 997 | version "0.2.0" 998 | resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" 999 | integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== 1000 | 1001 | safe-buffer@5.2.1, safe-buffer@~5.2.0: 1002 | version "5.2.1" 1003 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1004 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1005 | 1006 | safe-stable-stringify@^2.3.1: 1007 | version "2.4.2" 1008 | resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz#ec7b037768098bf65310d1d64370de0dc02353aa" 1009 | integrity sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA== 1010 | 1011 | "safer-buffer@>= 2.1.2 < 3": 1012 | version "2.1.2" 1013 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1014 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1015 | 1016 | secure-json-parse@^2.4.0: 1017 | version "2.7.0" 1018 | resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" 1019 | integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== 1020 | 1021 | semver@^5.7.1: 1022 | version "5.7.1" 1023 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 1024 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 1025 | 1026 | semver@~7.0.0: 1027 | version "7.0.0" 1028 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" 1029 | integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== 1030 | 1031 | send@0.18.0: 1032 | version "0.18.0" 1033 | resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" 1034 | integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 1035 | dependencies: 1036 | debug "2.6.9" 1037 | depd "2.0.0" 1038 | destroy "1.2.0" 1039 | encodeurl "~1.0.2" 1040 | escape-html "~1.0.3" 1041 | etag "~1.8.1" 1042 | fresh "0.5.2" 1043 | http-errors "2.0.0" 1044 | mime "1.6.0" 1045 | ms "2.1.3" 1046 | on-finished "2.4.1" 1047 | range-parser "~1.2.1" 1048 | statuses "2.0.1" 1049 | 1050 | serve-static@1.15.0: 1051 | version "1.15.0" 1052 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" 1053 | integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 1054 | dependencies: 1055 | encodeurl "~1.0.2" 1056 | escape-html "~1.0.3" 1057 | parseurl "~1.3.3" 1058 | send "0.18.0" 1059 | 1060 | setprototypeof@1.2.0: 1061 | version "1.2.0" 1062 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1063 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1064 | 1065 | side-channel@^1.0.4: 1066 | version "1.0.4" 1067 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 1068 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 1069 | dependencies: 1070 | call-bind "^1.0.0" 1071 | get-intrinsic "^1.0.2" 1072 | object-inspect "^1.9.0" 1073 | 1074 | simple-update-notifier@^1.0.7: 1075 | version "1.1.0" 1076 | resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" 1077 | integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== 1078 | dependencies: 1079 | semver "~7.0.0" 1080 | 1081 | sonic-boom@^3.0.0, sonic-boom@^3.1.0: 1082 | version "3.2.1" 1083 | resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.1.tgz#972ceab831b5840a08a002fa95a672008bda1c38" 1084 | integrity sha512-iITeTHxy3B9FGu8aVdiDXUVAcHMF9Ss0cCsAOo2HfCrmVGT3/DT5oYaeu0M/YKZDlKTvChEyPq0zI9Hf33EX6A== 1085 | dependencies: 1086 | atomic-sleep "^1.0.0" 1087 | 1088 | split2@^4.0.0: 1089 | version "4.1.0" 1090 | resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" 1091 | integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== 1092 | 1093 | stack-trace@0.0.x: 1094 | version "0.0.10" 1095 | resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" 1096 | integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== 1097 | 1098 | statuses@2.0.1: 1099 | version "2.0.1" 1100 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1101 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1102 | 1103 | string_decoder@^1.1.1: 1104 | version "1.3.0" 1105 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 1106 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 1107 | dependencies: 1108 | safe-buffer "~5.2.0" 1109 | 1110 | strip-json-comments@^3.1.1: 1111 | version "3.1.1" 1112 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1113 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1114 | 1115 | supports-color@^5.5.0: 1116 | version "5.5.0" 1117 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1118 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1119 | dependencies: 1120 | has-flag "^3.0.0" 1121 | 1122 | thread-stream@^2.0.0: 1123 | version "2.3.0" 1124 | resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33" 1125 | integrity sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA== 1126 | dependencies: 1127 | real-require "^0.2.0" 1128 | 1129 | to-regex-range@^5.0.1: 1130 | version "5.0.1" 1131 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1132 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1133 | dependencies: 1134 | is-number "^7.0.0" 1135 | 1136 | toidentifier@1.0.1: 1137 | version "1.0.1" 1138 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1139 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1140 | 1141 | touch@^3.1.0: 1142 | version "3.1.0" 1143 | resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" 1144 | integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== 1145 | dependencies: 1146 | nopt "~1.0.10" 1147 | 1148 | ts-node@^10.9.1: 1149 | version "10.9.1" 1150 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" 1151 | integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== 1152 | dependencies: 1153 | "@cspotcode/source-map-support" "^0.8.0" 1154 | "@tsconfig/node10" "^1.0.7" 1155 | "@tsconfig/node12" "^1.0.7" 1156 | "@tsconfig/node14" "^1.0.0" 1157 | "@tsconfig/node16" "^1.0.2" 1158 | acorn "^8.4.1" 1159 | acorn-walk "^8.1.1" 1160 | arg "^4.1.0" 1161 | create-require "^1.1.0" 1162 | diff "^4.0.1" 1163 | make-error "^1.1.1" 1164 | v8-compile-cache-lib "^3.0.1" 1165 | yn "3.1.1" 1166 | 1167 | type-is@~1.6.18: 1168 | version "1.6.18" 1169 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 1170 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 1171 | dependencies: 1172 | media-typer "0.3.0" 1173 | mime-types "~2.1.24" 1174 | 1175 | typescript@^4.9.5: 1176 | version "4.9.5" 1177 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" 1178 | integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== 1179 | 1180 | undefsafe@^2.0.5: 1181 | version "2.0.5" 1182 | resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" 1183 | integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== 1184 | 1185 | unpipe@1.0.0, unpipe@~1.0.0: 1186 | version "1.0.0" 1187 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1188 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 1189 | 1190 | util-deprecate@^1.0.1: 1191 | version "1.0.2" 1192 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1193 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 1194 | 1195 | utils-merge@1.0.1: 1196 | version "1.0.1" 1197 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 1198 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 1199 | 1200 | v8-compile-cache-lib@^3.0.1: 1201 | version "3.0.1" 1202 | resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" 1203 | integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== 1204 | 1205 | vary@^1, vary@~1.1.2: 1206 | version "1.1.2" 1207 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 1208 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 1209 | 1210 | winston@^2.2.0: 1211 | version "2.4.7" 1212 | resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.7.tgz#5791fe08ea7e90db090f1cb31ef98f32531062f1" 1213 | integrity sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg== 1214 | dependencies: 1215 | async "^2.6.4" 1216 | colors "1.0.x" 1217 | cycle "1.0.x" 1218 | eyes "0.1.x" 1219 | isstream "0.1.x" 1220 | stack-trace "0.0.x" 1221 | 1222 | wrappy@1: 1223 | version "1.0.2" 1224 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1225 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1226 | 1227 | yn@3.1.1: 1228 | version "3.1.1" 1229 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 1230 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 1231 | --------------------------------------------------------------------------------