├── .npmrc ├── packages ├── dappauth │ ├── .gitignore │ ├── babel.config.cjs │ ├── src │ │ ├── ABIs │ │ │ └── ERC1271.js │ │ ├── utils │ │ │ └── index.js │ │ └── index.js │ ├── CHANGELOG.md │ ├── test │ │ └── unit │ │ │ ├── provider-mock.js │ │ │ ├── jest.config.cjs │ │ │ ├── test-utils.js │ │ │ ├── contract-mock.js │ │ │ └── index.test.js │ ├── README.md │ ├── LICENSE │ ├── package.json │ └── rollup.config.js ├── blocto-sdk │ ├── .env.example │ ├── src │ │ ├── lib │ │ │ ├── storage │ │ │ │ ├── index.ts │ │ │ │ ├── memoryStorage.ts │ │ │ │ └── storage.ts │ │ │ ├── isEmail.ts │ │ │ ├── constant.ts │ │ │ ├── invariant.ts │ │ │ ├── utf8toHex.ts │ │ │ ├── addSelfRemovableHandler.ts │ │ │ ├── responseSessionGuard.ts │ │ │ ├── frame.ts │ │ │ ├── getEvmSupport.ts │ │ │ └── isValidTransaction.ts │ │ ├── providers │ │ │ ├── types │ │ │ │ ├── blocto.d.ts │ │ │ │ ├── aptos.d.ts │ │ │ │ └── ethereum.d.ts │ │ │ └── blocto.ts │ │ ├── main.ts │ │ ├── index.d.ts │ │ ├── __tests__ │ │ │ ├── isValidTransaction.test.js │ │ │ ├── ethereum.test.ts │ │ │ ├── fixtures │ │ │ │ └── getEvmSupport.ts │ │ │ └── index.test.js │ │ └── constants.ts │ ├── babel.config.json │ ├── .eslintrc.cjs │ ├── dev-cert │ │ └── index.js │ ├── jest.config.cjs │ ├── rollup.config.dev.js │ ├── .gitignore │ ├── package.json │ ├── README.md │ ├── rollup.config.js │ ├── example │ │ └── index.html │ └── tsconfig.json ├── tsconfig │ ├── package.json │ ├── react-library.json │ ├── nextjs.json │ └── base.json └── eslint-config-custom │ ├── index.js │ └── package.json ├── .husky └── commit-msg ├── .prettierrc ├── .github ├── pr-labeler.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── pr-labeler.yml │ ├── create-asana-attachment.yaml │ ├── test.yml │ ├── publish.yml │ └── release-branch.yml ├── adapters ├── wagmi-connector │ ├── src │ │ ├── index.ts │ │ ├── connector.ts │ │ └── connector.test.ts │ ├── .gitignore │ ├── vite.config.ts │ ├── tsconfig.json │ ├── package.json │ └── README.md ├── web3modal-connector │ ├── src │ │ ├── index.ts │ │ └── web3ModalConfig.ts │ ├── .gitignore │ ├── README.md │ ├── vite.config.ts │ ├── tsconfig.json │ ├── package.json │ └── CHANGELOG.md ├── aptos-wallet-adapter-plugin │ ├── jest.config.js │ ├── README.md │ ├── tsconfig.json │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── index.test.ts │ │ └── index.ts │ └── CHANGELOG.md ├── connectkit-connector │ ├── src │ │ ├── index.ts │ │ ├── constants │ │ │ └── index.tsx │ │ └── components │ │ │ └── BloctoLogo.tsx │ ├── .gitignore │ ├── vite.config.ts │ ├── tsconfig.json │ ├── README.md │ ├── package.json │ └── CHANGELOG.md ├── rainbowkit-connector │ ├── jest.config.js │ ├── tsconfig.json │ ├── package.json │ ├── README.md │ └── src │ │ ├── index.ts │ │ └── __tests__ │ │ └── index.test.ts └── web3-react-connector │ ├── README.md │ ├── tsconfig.json │ ├── package.json │ └── src │ └── index.ts ├── .eslintrc.js ├── .yarnrc ├── turbo.json ├── .changeset ├── config.json └── README.md ├── commitlint.config.js ├── LICENSE ├── package.json ├── .gitignore ├── CONTRIBUTING.md └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers = true 2 | -------------------------------------------------------------------------------- /packages/dappauth/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .nyc_output/ 3 | -------------------------------------------------------------------------------- /packages/blocto-sdk/.env.example: -------------------------------------------------------------------------------- 1 | SERVER=http://localhost:8702 2 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/storage/index.ts: -------------------------------------------------------------------------------- 1 | export * from './storage'; 2 | -------------------------------------------------------------------------------- /packages/blocto-sdk/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/blocto-sdk/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['custom'], 4 | }; 5 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit ${1} 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "printWidth": 80 6 | } 7 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/isEmail.ts: -------------------------------------------------------------------------------- 1 | export const isEmail = (value: string): boolean => /\S+@\S+\.\S+/.test(value); 2 | -------------------------------------------------------------------------------- /.github/pr-labeler.yml: -------------------------------------------------------------------------------- 1 | Feature: ['feature/*', 'feat/*'] 2 | Refactor: refactor/* 3 | BugFix: ['fix/*', 'bugfix/*'] 4 | HotFix: ['hotfix/*'] -------------------------------------------------------------------------------- /adapters/wagmi-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | export { blocto, createConnector } from './connector'; 2 | export type * from './connector'; 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | // This tells ESLint to load the config from the package `eslint-config-custom` 4 | extends: ['custom'], 5 | }; 6 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | export { BloctoConnector } from '@blocto/wagmi-connector'; 2 | export { default as BloctoWeb3ModalConfig } from './web3ModalConfig'; 3 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | lastUpdateCheck 1686022997016 6 | yarn-path ".yarn/releases/yarn-1.19.0.js" 7 | -------------------------------------------------------------------------------- /adapters/aptos-wallet-adapter-plugin/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | }; -------------------------------------------------------------------------------- /adapters/connectkit-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | export { BloctoConnector } from '@blocto/wagmi-connector'; 2 | export type * from '@blocto/wagmi-connector'; 3 | export { BLOCTO_CONFIG } from './constants'; -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'yarn' 4 | directory: '/' 5 | schedule: 6 | interval: 'daily' 7 | ignore: 8 | - dependency-name: 'web3' 9 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tsconfig", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "MIT", 6 | "publishConfig": { 7 | "access": "public" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/blocto-sdk/dev-cert/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | module.exports = { 4 | cert: fs.readFileSync(`${__dirname}/localhost.pem`), 5 | key: fs.readFileSync(`${__dirname}/localhost-key.pem`), 6 | }; 7 | -------------------------------------------------------------------------------- /adapters/rainbowkit-connector/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | extensionsToTreatAsEsm: [".ts", ".tsx"] 6 | }; -------------------------------------------------------------------------------- /packages/dappauth/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: true, 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"] 6 | }, 7 | "test": { 8 | "dependsOn": ["build"] 9 | }, 10 | "lint": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/constant.ts: -------------------------------------------------------------------------------- 1 | export enum ERROR_MESSAGE { 2 | INVALID_TRANSACTION = 'Invalid transaction', 3 | INVALID_TRANSACTIONS = 'Invalid transactions', 4 | INVALID_TRANSACTION_VALUE = 'Transaction params "value" should be hex-encoded string', 5 | } 6 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/invariant.ts: -------------------------------------------------------------------------------- 1 | // instead invariant from package, since all error will throw on production 2 | function invariant(condition: unknown, format: string): void { 3 | if (!condition) { 4 | throw new Error(format); 5 | } 6 | } 7 | export default invariant; 8 | -------------------------------------------------------------------------------- /packages/tsconfig/react-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "React Library", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "jsx": "react-jsx", 7 | "lib": ["ES2015"], 8 | "module": "ESNext", 9 | "target": "es6" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["eslint-config-custom", "tsconfig"] 11 | } 12 | -------------------------------------------------------------------------------- /adapters/wagmi-connector/.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 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/.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/blocto-sdk/src/lib/utf8toHex.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'buffer'; 2 | export type ValidInputTypes = Uint8Array | bigint | string | number | boolean; 3 | 4 | export const isHexString = (hex: ValidInputTypes) => 5 | typeof hex === 'string' && /^0x[0-9A-Fa-f]*$/.test(hex); 6 | 7 | export const utf8ToHex = (str: string) => { 8 | return Buffer.from(str, 'utf8').toString('hex'); 9 | }; 10 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/providers/types/blocto.d.ts: -------------------------------------------------------------------------------- 1 | import { EIP1193Provider } from 'eip1193-provider'; 2 | 3 | declare interface BloctoProviderInterface extends EIP1193Provider { 4 | isBlocto: boolean; 5 | isConnecting: boolean; 6 | appId: string; 7 | eventListeners: { 8 | [key: string]: Array<(arg?: any) => void>; 9 | }; 10 | } 11 | 12 | export default BloctoProviderInterface; 13 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/.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 | -------------------------------------------------------------------------------- /adapters/web3-react-connector/README.md: -------------------------------------------------------------------------------- 1 | # web3-react-connector 2 | 3 | Blocto SDK connector for web3-react. For usage, please refer to [Blocto SDK web3-react connector](https://docs.blocto.app/blocto-sdk/evm-sdk/web3-react-connector) 4 | 5 | ## Development 6 | 7 | ### Install Dependencies 8 | 9 | ```bash 10 | yarn add @blocto/web3-react-connector 11 | ``` 12 | 13 | ### Build 14 | 15 | ```bash 16 | yarn build 17 | ``` 18 | -------------------------------------------------------------------------------- /packages/blocto-sdk/jest.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'jsdom', 5 | transform: { 6 | '^.+\\.(ts|tsx)?$': 'ts-jest', 7 | '^.+\\.(js|jsx)$': 'babel-jest', 8 | }, 9 | testPathIgnorePatterns: ['node_modules/(?!variables/.*)', '/fixtures/', '\\.d\\.ts$'], 10 | automock: false, 11 | resetMocks: false, 12 | }; 13 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | 3 | 4 | 5 | ## Related Links 6 | 7 | 8 | 9 | **Asana**: 10 | 11 | ## Checklist 12 | 13 | - [ ] Pasted Asana link. 14 | - [ ] Tagged labels. 15 | 16 | ## Prerequisite/Related Pull Requests 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/eslint-config-custom/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'turbo', 4 | 'prettier', 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | ], 8 | parser: '@typescript-eslint/parser', 9 | plugins: ['@typescript-eslint'], 10 | root: true, 11 | rules: { 12 | '@typescript-eslint/no-explicit-any': 'off', 13 | }, 14 | env: { 15 | node: true, 16 | es6: true, 17 | browser: true, 18 | jest: true, 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/README.md: -------------------------------------------------------------------------------- 1 | # web3Modal-connector 2 | 3 | The Blocto configuration settings for web3Modal 4 | 5 | For usage, please refer to [Integrate with Web3Modal](https://docs.blocto.app/blocto-sdk/javascript-sdk/evm-sdk/integrate-with-web3modal) 6 | 7 | ## Usage 8 | 9 | ``` 10 | yarn add @blocto/web3modal-connector 11 | ``` 12 | 13 | ## Development 14 | 15 | ### Install Dependencies 16 | 17 | ```bash 18 | yarn 19 | ``` 20 | 21 | ### Build 22 | 23 | ``` 24 | yarn build 25 | ``` 26 | -------------------------------------------------------------------------------- /.github/workflows/pr-labeler.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/TimonVS/pr-labeler-action 2 | 3 | name: PR Labeler 4 | on: 5 | pull_request: 6 | types: [opened, ready_for_review] 7 | 8 | jobs: 9 | pr-labeler: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: TimonVS/pr-labeler-action@v3 13 | with: 14 | configuration-path: .github/pr-labeler.yml # optional, .github/pr-labeler.yml is the default value 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/addSelfRemovableHandler.ts: -------------------------------------------------------------------------------- 1 | interface RemovableEventHandler { 2 | (e: Event, callback: () => void): void; 3 | } 4 | 5 | export default ( 6 | eventType: string, 7 | handler: RemovableEventHandler, 8 | target: any = window 9 | ): void => { 10 | function listener(e: Event) { 11 | const removeEventListener = () => 12 | target.removeEventListener(eventType, listener); 13 | handler(e, removeEventListener); 14 | } 15 | target.addEventListener(eventType, listener); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/eslint-config-custom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-custom", 3 | "version": "0.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "private": true, 7 | "dependencies": { 8 | "@typescript-eslint/eslint-plugin": "^5.59.9", 9 | "@typescript-eslint/parser": "^5.59.9", 10 | "eslint": "^8.42.0", 11 | "eslint-config-prettier": "^8.8.0", 12 | "eslint-config-turbo": "1.10.1", 13 | "typescript": "^5.1.3" 14 | }, 15 | "publishConfig": { 16 | "access": "public" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/dappauth/src/ABIs/ERC1271.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | constant: true, 4 | inputs: [ 5 | { 6 | name: 'hash', 7 | type: 'bytes32', 8 | }, 9 | { 10 | name: '_signature', 11 | type: 'bytes', 12 | }, 13 | ], 14 | name: 'isValidSignature', 15 | outputs: [ 16 | { 17 | name: 'magicValue', 18 | type: 'bytes4', 19 | }, 20 | ], 21 | payable: false, 22 | stateMutability: 'view', 23 | type: 'function', 24 | }, 25 | ]; 26 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /adapters/aptos-wallet-adapter-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Blocto Plugin for Aptos Wallet Adapter 2 | 3 | A Blocto wallet plugin to be used with [Aptos Wallet Adapter](https://github.com/aptos-labs/aptos-wallet-adapter). 4 | 5 | ## Usage 6 | 7 | ```shell 8 | yarn add @blocto/aptos-wallet-adapter-plugin 9 | ``` 10 | 11 | or 12 | 13 | ```shell 14 | npm i @blocto/aptos-wallet-adapter-plugin 15 | ``` 16 | 17 | and follow the instructions [adapter for dapps](https://github.com/aptos-labs/aptos-wallet-adapter/tree/main/packages/wallet-adapter-react) 18 | -------------------------------------------------------------------------------- /adapters/wagmi-connector/vite.config.ts: -------------------------------------------------------------------------------- 1 | // vite.config.ts 2 | import { resolve } from 'path'; 3 | import { defineConfig } from 'vite'; 4 | import dts from 'vite-plugin-dts'; 5 | // https://vitejs.dev/guide/build.html#library-mode 6 | export default defineConfig({ 7 | build: { 8 | lib: { 9 | entry: resolve(__dirname, 'src/index.ts'), 10 | name: 'index', 11 | fileName: 'index', 12 | }, 13 | rollupOptions: { 14 | treeshake: { 15 | moduleSideEffects: false, 16 | }, 17 | }, 18 | }, 19 | plugins: [dts()], 20 | }); 21 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/vite.config.ts: -------------------------------------------------------------------------------- 1 | // vite.config.ts 2 | import { resolve } from 'path'; 3 | import { defineConfig } from 'vite'; 4 | import dts from 'vite-plugin-dts'; 5 | // https://vitejs.dev/guide/build.html#library-mode 6 | export default defineConfig({ 7 | build: { 8 | lib: { 9 | entry: resolve(__dirname, 'src/index.ts'), 10 | name: 'index', 11 | fileName: 'index', 12 | }, 13 | rollupOptions: { 14 | treeshake: { 15 | moduleSideEffects: false, 16 | }, 17 | }, 18 | }, 19 | plugins: [dts()], 20 | }); 21 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/vite.config.ts: -------------------------------------------------------------------------------- 1 | // vite.config.ts 2 | import { resolve } from 'path'; 3 | import { defineConfig } from 'vite'; 4 | import dts from 'vite-plugin-dts'; 5 | // https://vitejs.dev/guide/build.html#library-mode 6 | export default defineConfig({ 7 | build: { 8 | lib: { 9 | entry: resolve(__dirname, 'src/index.ts'), 10 | name: 'index', 11 | fileName: 'index', 12 | }, 13 | rollupOptions: { 14 | treeshake: { 15 | moduleSideEffects: false, 16 | }, 17 | }, 18 | }, 19 | plugins: [dts()], 20 | }); 21 | -------------------------------------------------------------------------------- /packages/tsconfig/nextjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Next.js", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "allowJs": true, 7 | "declaration": false, 8 | "declarationMap": false, 9 | "incremental": true, 10 | "jsx": "preserve", 11 | "lib": ["dom", "dom.iterable", "esnext"], 12 | "module": "esnext", 13 | "noEmit": true, 14 | "resolveJsonModule": true, 15 | "strict": false, 16 | "target": "es5" 17 | }, 18 | "include": ["src", "next-env.d.ts"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/tsconfig/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "inlineSources": false, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "preserveWatchOutput": true, 16 | "skipLibCheck": true, 17 | "strict": true 18 | }, 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/main.ts: -------------------------------------------------------------------------------- 1 | import EthereumProvider from './providers/ethereum'; 2 | import AptosProvider from './providers/aptos'; 3 | import { BloctoSDKConfig } from './index.d'; 4 | 5 | export default class BloctoSDK { 6 | ethereum?: EthereumProvider; 7 | aptos?: AptosProvider; 8 | 9 | constructor({ appId, ethereum, aptos }: BloctoSDKConfig) { 10 | if (ethereum) { 11 | this.ethereum = new EthereumProvider({ 12 | ...ethereum, 13 | appId, 14 | }); 15 | } 16 | if (aptos) { 17 | this.aptos = new AptosProvider({ 18 | ...aptos, 19 | appId, 20 | }); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/src/constants/index.tsx: -------------------------------------------------------------------------------- 1 | import { supportedConnectors } from 'connectkit'; 2 | import { BloctoLogo } from '../components/BloctoLogo'; 3 | 4 | type Spc = typeof supportedConnectors; 5 | 6 | const BLOCTO_CONFIG: Spc[number] = { 7 | id: 'blocto', 8 | name: 'Blocto', 9 | shortName: 'Blocto', 10 | logos: { 11 | default: , 12 | }, 13 | appUrls: { 14 | ios: 'https://apps.apple.com/app/blocto/id1481181682', 15 | android: 'https://play.google.com/store/apps/details?id=com.portto.blocto', 16 | }, 17 | scannable: false, 18 | extensionIsInstalled: () => true, 19 | }; 20 | 21 | export { BLOCTO_CONFIG }; 22 | -------------------------------------------------------------------------------- /packages/dappauth/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @blocto/dappauth 2 | 3 | ## 2.2.2 4 | 5 | ### Patch Changes 6 | 7 | - 48fa07a: fix: handle existedSDK handle window not defined 8 | 9 | ## 2.2.2-beta.0 10 | 11 | ### Patch Changes 12 | 13 | - 48fa07a: fix: handle existedSDK handle window not defined 14 | 15 | ## 2.2.1 16 | 17 | ### Patch Changes 18 | 19 | - 9609a4e: fix: build config and test Switched from Mocha to Jest 20 | 21 | ## 2.2.1-beta.0 22 | 23 | ### Patch Changes 24 | 25 | - 9609a4e: fix: build config and test Switched from Mocha to Jest 26 | 27 | ## 2.2.0 28 | 29 | ### Minor Changes 30 | 31 | - 5ae0ff0: restructure @blocto/dappauth and using rollup bundle 32 | -------------------------------------------------------------------------------- /adapters/wagmi-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": false, 19 | "noUnusedParameters": false, 20 | "noFallthroughCasesInSwitch": true 21 | 22 | }, 23 | "include": ["src"] 24 | } 25 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": false, 19 | "noUnusedParameters": false, 20 | "noFallthroughCasesInSwitch": true 21 | 22 | }, 23 | "include": ["src"] 24 | } 25 | -------------------------------------------------------------------------------- /adapters/aptos-wallet-adapter-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "inlineSources": false, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "preserveWatchOutput": true, 16 | "skipLibCheck": true, 17 | "strict": true, 18 | "lib": ["ES2015", "DOM"] 19 | }, 20 | "exclude": ["node_modules"] 21 | } 22 | -------------------------------------------------------------------------------- /adapters/rainbowkit-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "inlineSources": false, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "preserveWatchOutput": true, 16 | "skipLibCheck": true, 17 | "strict": true, 18 | "lib": ["ES2020", "DOM"], 19 | "target": "ES2020" 20 | }, 21 | "exclude": ["node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /adapters/web3-react-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "inlineSources": false, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "preserveWatchOutput": true, 16 | "skipLibCheck": true, 17 | "strict": true, 18 | "lib": ["ES2020", "DOM"], 19 | "target": "ES2020" 20 | }, 21 | "exclude": ["node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /packages/dappauth/src/utils/index.js: -------------------------------------------------------------------------------- 1 | export function isHexString(value) { 2 | return ( 3 | typeof value === 'string' && 4 | value.length % 2 === 0 && 5 | value.match(/^0x[0-9A-Fa-f]*$/) 6 | ); 7 | } 8 | 9 | export function removeHexPrefix(value) { 10 | return value.slice(0, 2) === '0x' ? value.slice(2) : value; 11 | } 12 | 13 | export function mergeErrors(errEOA, errCA) { 14 | const msgEOA = errEOA 15 | ? `errored with: ${errEOA.toString()}` 16 | : 'returned false'; 17 | return `Authorisation check failed and errored in 2 alternative flows. 'External Owned Account' check ${msgEOA} . 'Contract Account' check errored with: ${errCA.toString()}`; 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/create-asana-attachment.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | types: [opened, reopened] 4 | 5 | jobs: 6 | create-asana-attachment-job: 7 | runs-on: ubuntu-latest 8 | name: Create pull request attachments on Asana tasks 9 | steps: 10 | - name: Create pull request attachments 11 | uses: Asana/create-app-attachment-github-action@latest 12 | id: postAttachment 13 | with: 14 | asana-secret: ${{ secrets.ASANA_SECRET }} 15 | allowed-projects: | 16 | 1207145524635866 17 | 1207160002492686 18 | 1203400194794992 19 | - name: Log output status 20 | run: echo "Status is ${{ steps.postAttachment.outputs.status }}" 21 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react-jsx", 4 | "target": "ES2020", 5 | "useDefineForClassFields": true, 6 | "module": "ESNext", 7 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "resolvePackageJsonExports": false, 17 | 18 | /* Linting */ 19 | "strict": true, 20 | "noUnusedLocals": false, 21 | "noUnusedParameters": false, 22 | "noFallthroughCasesInSwitch": true 23 | 24 | }, 25 | "include": ["src"] 26 | } 27 | -------------------------------------------------------------------------------- /packages/dappauth/test/unit/provider-mock.js: -------------------------------------------------------------------------------- 1 | export default class MockProvider { 2 | constructor(mockContract) { 3 | this.mockContract = mockContract; 4 | } 5 | 6 | sendAsync(payload, callback) { 7 | const data = payload.params[0].data.substring(2); 8 | const methodCall = data.substring(0, 8); 9 | const methodParams = data.substring(8); 10 | 11 | try { 12 | const result = this.mockContract.run(methodCall, methodParams); 13 | const { jsonrpc, id } = payload; 14 | callback(null, { 15 | jsonrpc, 16 | id, 17 | result, 18 | }); 19 | } catch (error) { 20 | callback(error); 21 | } 22 | } 23 | 24 | send(payload, callback) { 25 | this.sendAsync(payload, callback); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/responseSessionGuard.ts: -------------------------------------------------------------------------------- 1 | import { removeItem } from './storage'; 2 | import { KEY_SESSION } from '../constants'; 3 | 4 | export interface ICustomError extends Error { 5 | error_code?: string; 6 | } 7 | 8 | export default async function responseSessionGuard( 9 | response: Response, 10 | key: KEY_SESSION, 11 | disconnectHandler?: () => void 12 | ): Promise { 13 | if (response.status === 403 || response.status === 401) { 14 | if (disconnectHandler) { 15 | disconnectHandler(); 16 | } 17 | removeItem(key); 18 | } 19 | if (!response.ok) { 20 | const data = await response.json(); 21 | const e: ICustomError = new Error(data?.message || 'unknown error'); 22 | e.error_code = data?.error_code; 23 | throw e; 24 | } 25 | return response.json(); 26 | } 27 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/README.md: -------------------------------------------------------------------------------- 1 | # connectkit-connector 2 | 3 | `integrateBloctoConfig` is used to integrate Blocto with ConnectKit. 4 | 5 | ## How to use 6 | 7 | ### Install package 8 | 9 | ``` 10 | yarn add @blocto/connectkit-connector 11 | ``` 12 | 13 | ### Example 14 | 15 | ```typescript 16 | import { getDefaultConfig, supportedConnectors } from 'connectkit'; 17 | import { integrateBloctoConfig } from '@blocto/connectkit-connector'; 18 | 19 | // ... 20 | 21 | let config = integrateBloctoConfig( 22 | createConfig( 23 | getDefaultConfig({ 24 | appName: 'ConnectKit CRA demo', 25 | autoConnect: false, 26 | chains: [mainnet, polygon, optimism, arbitrum], 27 | walletConnectProjectId: process.env.REACT_APP_WALLETCONNECT_PROJECT_ID!, 28 | }) 29 | ), 30 | supportedConnectors 31 | ); 32 | ``` -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/frame.ts: -------------------------------------------------------------------------------- 1 | const IFRAME_STYLE = 2 | 'width:100vw;height:100%;position:fixed;top:0;left:0;z-index:2147483646;border:none;box-sizing:border-box;color-scheme:light;inset:0px;display:block;pointer-events:auto;'; 3 | 4 | export function createFrame(url: string): HTMLIFrameElement { 5 | const frame = document.createElement('iframe'); 6 | 7 | frame.setAttribute('src', url); 8 | frame.setAttribute('style', IFRAME_STYLE); 9 | 10 | return frame; 11 | } 12 | 13 | export function attachFrame(frame: HTMLIFrameElement): void { 14 | document.body.appendChild(frame); 15 | } 16 | 17 | export function detatchFrame(frame: HTMLIFrameElement): void { 18 | const parentNode = frame && frame.parentNode; 19 | if (parentNode && parentNode.removeChild instanceof Function) { 20 | parentNode.removeChild(frame); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/getEvmSupport.ts: -------------------------------------------------------------------------------- 1 | export interface EvmSupportMapping { 2 | [id: string]: { 3 | chain_id: number; 4 | name: string; // backend defined chain name: ethereum, bsc, … 5 | display_name: string; // human readable name: Ethereum, Polygon, … 6 | network_type: string; // chain network type: mainnet / testnet / devnet 7 | blocto_service_environment: string; // backend service env: prod / dev (may return staging in future) 8 | rpc_endpoint_domains: string[]; // rpc endpoints whitelist 9 | }; 10 | } 11 | 12 | export async function getEvmSupport(): Promise { 13 | const { networks } = await fetch('https://api.blocto.app/networks/evm').then( 14 | (response) => response.json() 15 | ); 16 | const evmSupportMap = networks.reduce( 17 | (a: any, v: any) => ({ ...a, [v.chain_id]: v }), 18 | {} 19 | ); 20 | return evmSupportMap; 21 | } 22 | -------------------------------------------------------------------------------- /adapters/aptos-wallet-adapter-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/aptos-wallet-adapter-plugin", 3 | "version": "0.2.11", 4 | "description": "Blocto Wallet plugin to use with Aptos Wallet Adapter", 5 | "author": "Blocto Wallet", 6 | "main": "./dist/index.js", 7 | "module": "./dist/index.mjs", 8 | "types": "./dist/index.d.ts", 9 | "license": "Apache-2.0", 10 | "exports": { 11 | "require": "./dist/index.js", 12 | "import": "./dist/index.mjs", 13 | "types": "./dist/index.d.ts" 14 | }, 15 | "scripts": { 16 | "build": "tsup src/index.ts --format esm,cjs --dts", 17 | "test": "jest", 18 | "lint": "eslint src --ext .ts" 19 | }, 20 | "dependencies": { 21 | "@aptos-labs/wallet-adapter-core": "^2.2.0", 22 | "@blocto/sdk": "^0.10.4", 23 | "aptos": "^1.9.1" 24 | }, 25 | "devDependencies": { 26 | "@types/jest": "^29.5.2", 27 | "jest": "^29.3.1", 28 | "ts-jest": "^29.0.3", 29 | "tsup": "^6.5.0", 30 | "typescript": "^5.1.3" 31 | }, 32 | "files": [ 33 | "/dist" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | "module.exports = {extends: ['@commitlint/config-conventional']}"; 2 | 3 | module.exports = { 4 | extends: ['@commitlint/config-conventional'], 5 | rules: { 6 | 'type-enum': [ 7 | 2, 8 | 'always', 9 | [ 10 | 'feat', 11 | 'fix', 12 | 'docs', 13 | 'style', 14 | 'refactor', 15 | 'perf', 16 | 'test', 17 | 'build', 18 | 'ci', 19 | 'chore', 20 | 'revert', 21 | ], 22 | ], 23 | 'subject-exclamation-mark': [2, 'never'], 24 | 'body-leading-blank': [1, 'always'], 25 | 'footer-leading-blank': [1, 'always'], 26 | 'header-max-length': [2, 'always', 72], 27 | 'scope-case': [2, 'always', 'lower-case'], 28 | 'subject-case': [ 29 | 2, 30 | 'never', 31 | ['sentence-case', 'start-case', 'pascal-case', 'upper-case'], 32 | ], 33 | 'subject-empty': [2, 'never'], 34 | 'subject-full-stop': [2, 'never', '.'], 35 | 'type-case': [2, 'always', 'lower-case'], 36 | 'type-empty': [2, 'never'], 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /packages/dappauth/README.md: -------------------------------------------------------------------------------- 1 | # dappauth.js 2 | dappauth.js is a tool that can verify EOA signature and smart contract signature (ERC1271). 3 | 4 | ## Usage 5 | ```js 6 | const Web3 = require('web3'); 7 | const DappAuth = require('@blocto/dappauth'); 8 | 9 | const dappAuth = new DappAuth(new Web3.providers.HttpProvider('http://localhost:8545')); 10 | 11 | async function debug() { 12 | const challenge = 'foo'; 13 | const signature = 14 | '0x49b5e108d0b7ce795125acbc08b331aad170e4afe8daa5b4b484d12b9253316c4ca0cb36cec51682bcc9a65d6cb28002bd4835845d8f1de21afafe1132eaed3d1b28171e3bf436f2301c0bd657501cafb2a9344efe042495adba2852858db559da2fb4280007de4d631b9357493a979c4024927aec580ef3a22603918eb3b3071b1c'; 15 | const address = '0x86aa354fc865925f945b803ceae0b3f9d856b269'; 16 | 17 | try { 18 | const isAuthorizedSigner = await dappAuth.isAuthorizedSigner( 19 | challenge, 20 | signature, 21 | address, 22 | ); 23 | 24 | console.log(isAuthorizedSigner); // true 25 | } catch (e) { 26 | console.log(e); 27 | } 28 | } 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/storage/memoryStorage.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | interface Window { 3 | memoryStorage: MemoryStorage; 4 | } 5 | } 6 | 7 | export const isStorageSupported = () => { 8 | if (typeof window === 'undefined') { 9 | return false; 10 | } 11 | try { 12 | window.sessionStorage.setItem('local_storage_supported', '1'); 13 | const result = window.sessionStorage.getItem('local_storage_supported'); 14 | window.sessionStorage.removeItem('local_storage_supported'); 15 | return result === '1'; 16 | } catch (error) { 17 | return false; 18 | } 19 | }; 20 | 21 | class MemoryStorage { 22 | storage = {}; 23 | 24 | getItem(key: string): string | null { 25 | return (this as any)[key] || null; 26 | } 27 | 28 | setItem(key: string, value: unknown): void { 29 | (this.storage as any)[key] = value; 30 | } 31 | 32 | removeItem(key: string): void { 33 | delete (this.storage as any)[key]; 34 | } 35 | } 36 | 37 | const memoryStorage = 38 | typeof window !== 'undefined' ? window.memoryStorage : new MemoryStorage(); 39 | 40 | export default memoryStorage; 41 | export { MemoryStorage }; 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 portto (Blocto) 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 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, ready_for_review] 6 | 7 | jobs: 8 | build: 9 | name: Build and Test 10 | timeout-minutes: 15 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout Repo 15 | uses: actions/checkout@v3 16 | 17 | - name: Cache turbo build setup 18 | uses: actions/cache@v3 19 | with: 20 | path: .turbo 21 | key: ${{ runner.os }}-turbo-${{ github.sha }} 22 | restore-keys: | 23 | ${{ runner.os }}-turbo- 24 | 25 | - name: Setup Node.js 18 26 | uses: actions/setup-node@v3 27 | with: 28 | node-version: 18 29 | 30 | - name: Install dependencies 31 | run: yarn 32 | 33 | - name: Lint, Test, and Try to Build 34 | id: testWithCache 35 | run: yarn turbo lint test build --cache-dir=.turbo 36 | continue-on-error: true 37 | 38 | - name: Try to do again without cache 39 | if: steps.testWithCache.outcome == 'failure' 40 | run: yarn turbo lint test build --force --cache-dir=.turbo 41 | -------------------------------------------------------------------------------- /adapters/wagmi-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/wagmi-connector", 3 | "description": "Blocto wallet connector extend from wagmi Connector", 4 | "author": "Calvin Chang", 5 | "version": "2.0.5", 6 | "type": "module", 7 | "main": "./dist/index.umd.cjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "license": "Apache-2.0", 11 | "exports": { 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.umd.cjs" 14 | }, 15 | "scripts": { 16 | "build": "tsc && vite build", 17 | "lint": "eslint src --ext .ts", 18 | "test": "vitest run --coverage" 19 | }, 20 | "devDependencies": { 21 | "@types/node": "^20.2.5", 22 | "@vitest/coverage-v8": "^1.2.0", 23 | "@wagmi/chains": "^1.8.0", 24 | "@wagmi/core": "^2.2.0", 25 | "typescript": "^5.1.3", 26 | "viem": "^2.x", 27 | "vite": "^4.3.9", 28 | "vite-plugin-dts": "^2.3.0", 29 | "vitest": "^1.2.0" 30 | }, 31 | "files": [ 32 | "/dist" 33 | ], 34 | "dependencies": { 35 | "@blocto/sdk": "^0.10.4" 36 | }, 37 | "peerDependencies": { 38 | "@wagmi/core": "^2.2.0", 39 | "viem": "2.x" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/dappauth/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Dapper Labs, Inc. 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 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/index.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line spaced-comment 2 | /// 3 | 4 | import { BaseConfig } from './constants'; 5 | import { 6 | EthereumProviderConfig, 7 | EthereumProviderInterface, 8 | } from './providers/types/ethereum.d'; 9 | import { 10 | AptosProviderConfig, 11 | AptosProviderInterface, 12 | } from './providers/types/aptos.d'; 13 | import * as AptosTypes from './providers/types/aptos.d'; 14 | import * as EthereumTypes from './providers/types/ethereum.d'; 15 | 16 | export * from './providers/types/blocto.d'; 17 | export { 18 | BaseConfig, 19 | EthereumProviderConfig, 20 | EthereumProviderInterface, 21 | AptosProviderConfig, 22 | AptosProviderInterface, 23 | // Keep above types for backward compatibility 24 | AptosTypes, 25 | EthereumTypes, 26 | }; 27 | export declare interface BloctoSDKConfig extends BaseConfig { 28 | ethereum?: EthereumProviderConfig; 29 | aptos?: AptosProviderConfig; 30 | } 31 | declare class BloctoSDK { 32 | ethereum?: EthereumProviderInterface; 33 | aptos?: AptosProviderInterface; 34 | constructor(config: BloctoSDKConfig); 35 | } 36 | 37 | export default BloctoSDK; 38 | -------------------------------------------------------------------------------- /packages/blocto-sdk/rollup.config.dev.js: -------------------------------------------------------------------------------- 1 | import commonjs from 'rollup-plugin-commonjs'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | import typescript from 'rollup-plugin-typescript'; 4 | import json from 'rollup-plugin-json'; 5 | import polyfills from 'rollup-plugin-node-polyfills'; 6 | import alias from '@rollup/plugin-alias'; 7 | import { babel } from '@rollup/plugin-babel'; 8 | 9 | const config = { 10 | input: 'src/main.ts', 11 | output: { 12 | file: 'dev/bundle.js', 13 | format: 'umd', 14 | name: 'BloctoSDK', 15 | }, 16 | plugins: [ 17 | alias({ 18 | entries: { 19 | 'readable-stream': 'stream', 20 | }, 21 | }), 22 | resolve({ 23 | preferBuiltins: true, 24 | browser: true, 25 | }), 26 | typescript(), 27 | commonjs({ 28 | include: 'node_modules/**', 29 | namedExports: { 30 | 'node_modules/js-sha3/src/sha3.js': ['keccak_256'], 31 | }, 32 | }), 33 | json(), 34 | babel({ 35 | babelHelpers: 'inline', 36 | exclude: 'node_modules/**', 37 | presets: [['@babel/preset-env']], 38 | }), 39 | polyfills(), 40 | ], 41 | }; 42 | 43 | export default config; 44 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/connectkit-connector", 3 | "description": "blocto wallet connector to use with connectkit", 4 | "author": "Blocto Wallet", 5 | "version": "0.2.3", 6 | "type": "module", 7 | "main": "./dist/index.umd.cjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "license": "Apache-2.0", 11 | "exports": { 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.umd.cjs" 14 | }, 15 | "scripts": { 16 | "build": "tsc && vite build" 17 | }, 18 | "devDependencies": { 19 | "@types/node": "^20.2.5", 20 | "@types/react": "^18", 21 | "connectkit": "^1", 22 | "react": "^18", 23 | "typescript": "^5.1.3", 24 | "viem": "^1.2.9", 25 | "vite": "^4.3.9", 26 | "vite-plugin-dts": "^2.3.0", 27 | "wagmi": "^1" 28 | }, 29 | "files": [ 30 | "/dist" 31 | ], 32 | "dependencies": { 33 | "@blocto/wagmi-connector": "npm:@blocto/wagmi-connector@^1.3.1" 34 | }, 35 | "peerDependencies": { 36 | "connectkit": "^1.5.3", 37 | "react": "^18", 38 | "viem": "^1", 39 | "wagmi": "^1" 40 | }, 41 | "resolutions": { 42 | "viem": "1.3.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/web3modal-connector", 3 | "description": "Blocto connector extend from wagmi Connector to use with web3modal", 4 | "author": "Blocto Wallet", 5 | "version": "0.1.4", 6 | "type": "module", 7 | "main": "./dist/index.umd.cjs", 8 | "module": "./dist/index.js", 9 | "types": "./dist/index.d.ts", 10 | "license": "Apache-2.0", 11 | "keywords": [ 12 | "web3modal", 13 | "wagmi", 14 | "javascript", 15 | "typescript", 16 | "web3", 17 | "context", 18 | "frontend", 19 | "dapp", 20 | "blocto", 21 | "web3-react", 22 | "blocto-sdk", 23 | "eth", 24 | "ethereum" 25 | ], 26 | "exports": { 27 | "import": "./dist/index.js", 28 | "require": "./dist/index.umd.cjs" 29 | }, 30 | "scripts": { 31 | "build": "tsc && vite build", 32 | "lint": "eslint src --ext .ts" 33 | }, 34 | "devDependencies": { 35 | "@types/node": "^20.2.5", 36 | "typescript": "^5.1.3", 37 | "vite": "^4.3.9", 38 | "vite-plugin-dts": "^2.3.0" 39 | }, 40 | "files": [ 41 | "/dist" 42 | ], 43 | "dependencies": { 44 | "@blocto/wagmi-connector": "npm:@blocto/wagmi-connector@^1.3.1" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blocto-sdk", 3 | "version": "0.1.0", 4 | "private": true, 5 | "packageManager": "yarn@1.19.0", 6 | "scripts": { 7 | "build": "turbo run build", 8 | "dev": "turbo run dev", 9 | "lint": "turbo run lint", 10 | "format": "prettier --write \"**/*.{ts,tsx,md}\"", 11 | "test": "turbo run test", 12 | "beta-ver": "changeset pre enter beta && changeset version && changeset pre exit", 13 | "ver": "changeset version", 14 | "beta-release": "turbo run test && changeset pre enter beta && changeset version && turbo run build && changeset publish && changeset pre exit", 15 | "release": "turbo run build && changeset publish && git push origin --tags", 16 | "postinstall": "husky install", 17 | "prepare": "husky install" 18 | }, 19 | "devDependencies": { 20 | "@changesets/cli": "^2.26.1", 21 | "@commitlint/cli": "^17.6.5", 22 | "@commitlint/config-angular": "^17.6.5", 23 | "@commitlint/config-conventional": "^17.6.5", 24 | "eslint": "^8.42.0", 25 | "eslint-config-custom": "*", 26 | "husky": "^8.0.0", 27 | "prettier": "^2.8.8", 28 | "turbo": "^1.10.1" 29 | }, 30 | "workspaces": [ 31 | "packages/*", 32 | "adapters/*" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/isValidTransaction.ts: -------------------------------------------------------------------------------- 1 | import { ERROR_MESSAGE } from './constant'; 2 | import { isHexString } from './utf8toHex'; 3 | 4 | export const isValidTransaction = ( 5 | transaction: Record 6 | ): { isValid: boolean; invalidMsg?: string } => { 7 | if ( 8 | !transaction || 9 | typeof transaction !== 'object' || 10 | !('from' in transaction) 11 | ) { 12 | return { isValid: false, invalidMsg: ERROR_MESSAGE.INVALID_TRANSACTION }; 13 | } 14 | if (transaction.value && !isHexString(transaction.value)) { 15 | return { 16 | isValid: false, 17 | invalidMsg: ERROR_MESSAGE.INVALID_TRANSACTION_VALUE, 18 | }; 19 | } 20 | 21 | return { isValid: true }; 22 | }; 23 | 24 | export const isValidTransactions = ( 25 | transactions: Record[] 26 | ): { isValid: boolean; invalidMsg?: string } => { 27 | if (!Array.isArray(transactions)) { 28 | return { isValid: false, invalidMsg: ERROR_MESSAGE.INVALID_TRANSACTIONS }; 29 | } 30 | 31 | for (let i = 0; i < transactions.length; i++) { 32 | const { isValid, invalidMsg } = isValidTransaction(transactions[i]); 33 | 34 | if (!isValid) { 35 | return { isValid, invalidMsg }; 36 | } 37 | } 38 | 39 | return { isValid: true }; 40 | }; 41 | -------------------------------------------------------------------------------- /adapters/rainbowkit-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/rainbowkit-connector", 3 | "version": "2.0.3", 4 | "description": "blocto wallet connector to use rainbowkit", 5 | "author": "Blocto Wallet", 6 | "main": "./dist/index.js", 7 | "module": "./dist/index.mjs", 8 | "types": "./dist/index.d.ts", 9 | "license": "Apache-2.0", 10 | "keywords": [ 11 | "rainbowkit", 12 | "react", 13 | "wagmi", 14 | "javascript", 15 | "typescript", 16 | "web3", 17 | "context", 18 | "frontend", 19 | "dapp", 20 | "blocto", 21 | "web3-react", 22 | "blocto-sdk", 23 | "eth", 24 | "ethereum" 25 | ], 26 | "exports": { 27 | "require": "./dist/index.js", 28 | "import": "./dist/index.mjs", 29 | "types": "./dist/index.d.ts" 30 | }, 31 | "scripts": { 32 | "build": "tsup src/index.ts --format esm,cjs --dts", 33 | "lint": "eslint src --ext .ts" 34 | }, 35 | "dependencies": { 36 | "@rainbow-me/rainbowkit": "^2.0.5", 37 | "@blocto/wagmi-connector": "^2.0.5" 38 | }, 39 | "devDependencies": { 40 | "@types/jest": "^29.5.2", 41 | "jest": "^29.3.1", 42 | "ts-jest": "^29.0.3", 43 | "tsup": "^6.5.0", 44 | "typescript": "^5.1.3" 45 | }, 46 | "files": [ 47 | "/dist" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /adapters/web3-react-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/web3-react-connector", 3 | "version": "1.0.9", 4 | "description": "A Blocto SDK connector for web3-react", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.mjs", 7 | "types": "./dist/index.d.ts", 8 | "license": "MIT", 9 | "files": [ 10 | "/dist" 11 | ], 12 | "publishConfig": { 13 | "access": "public" 14 | }, 15 | "exports": { 16 | "require": "./dist/index.js", 17 | "import": "./dist/index.mjs", 18 | "types": "./dist/index.d.ts" 19 | }, 20 | "scripts": { 21 | "build": "tsup src/index.ts --format esm,cjs --dts", 22 | "lint": "eslint src --ext .ts" 23 | }, 24 | "keywords": [ 25 | "react", 26 | "react-hooks", 27 | "hooks", 28 | "javascript", 29 | "typescript", 30 | "web3", 31 | "context", 32 | "frontend", 33 | "dapp", 34 | "blocto", 35 | "web3-react", 36 | "blocto-sdk", 37 | "eth", 38 | "ethereum" 39 | ], 40 | "author": "Chiaki.C", 41 | "repository": { 42 | "type": "git", 43 | "url": "git://github.com/portto/blocto-sdk.git" 44 | }, 45 | "dependencies": { 46 | "@blocto/sdk": "^0.10.4", 47 | "@web3-react/types": "^8.1.2-beta.0" 48 | }, 49 | "devDependencies": { 50 | "tsup": "^7.2.0", 51 | "typescript": "^5.1.3" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/blocto-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | dist 34 | es 35 | 36 | # dev build 37 | dev 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # Typescript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | # gatsby files 62 | .cache/ 63 | public 64 | 65 | # Mac files 66 | .DS_Store 67 | 68 | # Yarn 69 | yarn-error.log 70 | .pnp/ 71 | .pnp.js 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # IntelijIDEA 76 | .idea 77 | 78 | # cert keys 79 | dev-cert/*.pem 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | dist 34 | es 35 | 36 | # dev build 37 | dev 38 | 39 | # dependencies 40 | node_modules 41 | .pnp 42 | .pnp.js 43 | 44 | # Typescript v1 declaration files 45 | typings/ 46 | 47 | # Optional npm cache directory 48 | .npm 49 | 50 | # Optional eslint cache 51 | .eslintcache 52 | 53 | # Optional REPL history 54 | .node_repl_history 55 | 56 | # Output of 'npm pack' 57 | *.tgz 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # Mac files 63 | .DS_Store 64 | 65 | # Yarn 66 | yarn-error.log 67 | .pnp/ 68 | .pnp.js 69 | # Yarn Integrity file 70 | .yarn-integrity 71 | 72 | # IntelijIDEA 73 | .idea 74 | 75 | # cert keys 76 | dev-cert/*.pem 77 | 78 | # turbo repo 79 | .turbo 80 | 81 | # vercel 82 | .vercel 83 | 84 | # debug 85 | npm-debug.log* 86 | yarn-debug.log* 87 | yarn-error.log* 88 | 89 | # next.js 90 | .next 91 | /out/ -------------------------------------------------------------------------------- /packages/blocto-sdk/src/providers/blocto.ts: -------------------------------------------------------------------------------- 1 | // The root class for all providers 2 | 3 | import { EIP1193Provider, RequestArguments } from 'eip1193-provider'; 4 | import { EIP1193_EVENTS } from '../constants'; 5 | import { DEFAULT_APP_ID } from '../constants'; 6 | 7 | class BloctoProvider implements EIP1193Provider { 8 | isBlocto = true; 9 | 10 | isConnecting = false; 11 | appId: string; 12 | 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | eventListeners: { [key: string]: Array<(arg: any) => void> } = {}; 15 | 16 | constructor() { 17 | // init event listeners 18 | EIP1193_EVENTS.forEach((event) => { 19 | this.eventListeners[event] = []; 20 | }); 21 | this.appId = DEFAULT_APP_ID; 22 | } 23 | 24 | // implement by children 25 | // eslint-disable-next-line 26 | async request(payload: RequestArguments | Array) {} 27 | 28 | on(event: string, listener: (arg: any) => void): void { 29 | if (!EIP1193_EVENTS.includes(event)) return; 30 | 31 | this.eventListeners[event].push(listener); 32 | } 33 | 34 | // @todo: implement it 35 | // eslint-disable-next-line 36 | once() {} 37 | 38 | removeListener(event: string, listener: (arg: any) => void): void { 39 | const listeners = this.eventListeners[event]; 40 | const index = listeners.findIndex((item) => item === listener); 41 | if (index !== -1) { 42 | this.eventListeners[event].splice(index, 1); 43 | } 44 | } 45 | 46 | // alias removeListener 47 | off = this.removeListener; 48 | } 49 | 50 | export default BloctoProvider; 51 | -------------------------------------------------------------------------------- /adapters/wagmi-connector/README.md: -------------------------------------------------------------------------------- 1 | # wagmi-connector 2 | 3 | The `BloctoConnector` extends from the [wagmi](https://wagmi.sh/) `Connector`, allowing Blocto to be used with the most popular **Connect Wallet kits** (such as Web3Modal, ConnectKit, etc.) as solutions. 4 | 5 | For usage, please refer to below links: 6 | - [Blocto SDK Integrate with Web3Modal](https://docs.blocto.app/blocto-sdk/javascript-sdk/evm-sdk/integrate-with-web3modal) 7 | - [Blocto SDK Integrate with RainbowKit](https://docs.blocto.app/blocto-sdk/javascript-sdk/evm-sdk/integrate-with-rainbowkit) 8 | - [Blocto SDK Integrate with thirdweb](https://docs.blocto.app/blocto-sdk/javascript-sdk/evm-sdk/integrate-with-thirdweb) 9 | 10 | ## Migration Guide 11 | If you are coming from an earlier version of `@blocto/wagmi-connector`, 12 | you can see breaking changes in the list below. 13 | 14 | ### 1.2.0 Breaking Changes 15 | 1. Removed `BloctoWeb3modalConfig` exported; instead, we use `@blocto/web3modal-connector` to replace support for **Web3Modal** 16 | 17 | ```bash 18 | npm uninstall @blocto/wagmi-connector 19 | npm install @blocto/web3modal-connector 20 | ``` 21 | 22 | 2. Removed `chainId` & `rpc` parameters from `BloctoConnector` constructor. 23 | 24 | ```diff 25 | - new BloctoConnector({ chains, options: { appId, chainId, rpc } }) 26 | + new BloctoConnector({ chains, options: { appId } }) 27 | ``` 28 | 29 | ## Usage 30 | 31 | ``` 32 | yarn add @blocto/wagmi-connector 33 | ``` 34 | 35 | ## Development 36 | 37 | ### Install Dependencies 38 | 39 | ```bash 40 | yarn 41 | ``` 42 | 43 | ### Build 44 | 45 | ``` 46 | yarn build 47 | ``` 48 | -------------------------------------------------------------------------------- /adapters/aptos-wallet-adapter-plugin/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import { BloctoWallet } from '../index'; 2 | 3 | /* 4 | Basic tests to make sure basic variables and functions are defined on the wallet 5 | 6 | */ 7 | describe('BloctoWallet', () => { 8 | const wallet = new BloctoWallet({ 9 | bloctoAppId: '6f6b97c5-d97b-4799-8ad7-d7e8426d3369', 10 | }); 11 | 12 | test('defines name', () => { 13 | expect(typeof wallet.name).toBe('string'); 14 | }); 15 | 16 | test('defines url', () => { 17 | expect(typeof wallet.url).toBe('string'); 18 | }); 19 | 20 | test('defines icon', () => { 21 | expect(typeof wallet.icon).toBe('string'); 22 | }); 23 | 24 | test('defines connect()', () => { 25 | expect(typeof wallet.connect).toBe('function'); 26 | }); 27 | 28 | test('defines account()', () => { 29 | expect(typeof wallet.account).toBe('function'); 30 | }); 31 | 32 | test('defines disconnect()', () => { 33 | expect(typeof wallet.disconnect).toBe('function'); 34 | }); 35 | 36 | test('defines signAndSubmitTransaction()', () => { 37 | expect(typeof wallet.signAndSubmitTransaction).toBe('function'); 38 | }); 39 | 40 | test('defines signMessage()', () => { 41 | expect(typeof wallet.signMessage).toBe('function'); 42 | }); 43 | 44 | test('defines onNetworkChange()', () => { 45 | expect(typeof wallet.onNetworkChange).toBe('function'); 46 | }); 47 | 48 | test('defines onAccountChange()', () => { 49 | expect(typeof wallet.onAccountChange).toBe('function'); 50 | }); 51 | 52 | test('defines network()', () => { 53 | expect(typeof wallet.network).toBe('function'); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /packages/dappauth/test/unit/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | globals: { 4 | 'ts-jest': { 5 | tsconfig: './test/tsconfig.json', 6 | }, 7 | }, 8 | rootDir: '../..', 9 | transform: { 10 | '^.+\\.(ts|tsx)?$': 'ts-jest', 11 | '^.+\\.(js|jsx)$': 'babel-jest', 12 | }, 13 | moduleNameMapper: { 14 | '^(\\.{1,2}/.*)\\.js$': '$1', 15 | }, 16 | verbose: false, 17 | /** 18 | * restoreMocks [boolean] 19 | * 20 | * Default: false 21 | * 22 | * Automatically restore mock state between every test. 23 | * Equivalent to calling jest.restoreAllMocks() between each test. 24 | * This will lead to any mocks having their fake implementations removed 25 | * and restores their initial implementation. 26 | */ 27 | restoreMocks: true, 28 | /** 29 | * resetModules [boolean] 30 | * 31 | * Default: false 32 | * 33 | * By default, each test file gets its own independent module registry. 34 | * Enabling resetModules goes a step further and resets the module registry before running each individual test. 35 | * This is useful to isolate modules for every test so that local module state doesn't conflict between tests. 36 | * This can be done programmatically using jest.resetModules(). 37 | */ 38 | resetModules: true, 39 | testMatch: ['/test/unit/**/*.(spec|test).(js|ts)'], 40 | coverageDirectory: '../../.coverage/unit', 41 | collectCoverageFrom: ['src/**'], 42 | collectCoverage: true, 43 | coverageReporters: [ 44 | [ 45 | 'json', 46 | { 47 | file: 'dappauth-unit-coverage.json', 48 | }, 49 | ], 50 | ], 51 | }; 52 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to npm 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: Publish to npm 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Repo 16 | uses: actions/checkout@v3 17 | 18 | - name: Setup Node.js 18 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: 18 22 | 23 | - name: Install Dependencies 24 | run: yarn 25 | 26 | - name: Attempting to publish packages to npm 27 | uses: changesets/action@v1 28 | with: 29 | publish: yarn release 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 33 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 34 | 35 | - name: Set version from publishedPackages 36 | id: setVersion 37 | if: steps.changesets.outputs.published == 'true' 38 | env: 39 | PACKAGE_VERSION: ${{ steps.changesets.outputs.publishedPackages }} 40 | run: echo "PACKAGE_VERSION=$(echo $PACKAGE_VERSION | jq -r '.[0].version')" >> $GITHUB_OUTPUT 41 | 42 | - name: Trigger example repo github action 43 | if: steps.changesets.outputs.published == 'true' 44 | run: | 45 | curl -H "Authorization: Bearer ${{ secrets.DEV_GITHUB_TOKEN }}" \ 46 | -H 'Accept: application/vnd.github.everest-preview+json' \ 47 | "https://api.github.com/repos/blocto/blocto-sdk-examples/dispatches" \ 48 | -d '{"event_type": "update-package", "client_payload": {"version": "${{ steps.setVersion.outputs.PACKAGE_VERSION }}" }}' 49 | -------------------------------------------------------------------------------- /adapters/rainbowkit-connector/README.md: -------------------------------------------------------------------------------- 1 | # rainbowkit-connector 2 | 3 | [Blocto SDK](https://docs.blocto.app/blocto-sdk/javascript-sdk) connector for [RainbowKit](https://www.rainbowkit.com/) React library. 4 | 5 | ## How to use 6 | 7 | ### Install package 8 | 9 | `yarn add @blocto/rainbowkit-connector` 10 | 11 | ### Use it in your code 12 | 13 | ```TSX 14 | import { 15 | getDefaultWallets, 16 | connectorsForWallets, 17 | RainbowKitProvider, 18 | ConnectButton 19 | } from "@rainbow-me/rainbowkit"; 20 | import { configureChains, createConfig, WagmiConfig } from "wagmi"; 21 | import { polygon, optimism, arbitrum, bsc, mainnet } from "wagmi/chains"; 22 | import { publicProvider } from 'wagmi/providers/public'; 23 | import { alchemyProvider } from 'wagmi/providers/alchemy'; 24 | import { bloctoWallet } from '@blocto/rainbowkit-connector'; 25 | 26 | const { chains, publicClient, webSocketPublicClient } = configureChains( 27 | [polygon, optimism, arbitrum, bsc, mainnet], 28 | [alchemyProvider({ apiKey: process.env.ALCHEMY_ID || "" }), publicProvider()] 29 | ); 30 | 31 | const { wallets } = getDefaultWallets({ 32 | appName: "My RainbowKit App", 33 | projectId: "YOUR_PROJECT_ID", 34 | chains 35 | }); 36 | 37 | const connectors = connectorsForWallets([ 38 | ...wallets, 39 | { 40 | groupName: "Other", 41 | wallets: [ 42 | bloctoWallet({ chains }), // add BloctoWallet 43 | ] 44 | } 45 | ]); 46 | 47 | const wagmiConfig = createConfig({ 48 | autoConnect: true, 49 | connectors, 50 | publicClient, 51 | webSocketPublicClient, 52 | }); 53 | 54 | export const App = () => { 55 | return ( 56 | 57 | 58 | 59 | 60 | 61 | ); 62 | }; 63 | 64 | ``` 65 | -------------------------------------------------------------------------------- /.github/workflows/release-branch.yml: -------------------------------------------------------------------------------- 1 | name: Create version PR from release branch 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'release**' 7 | - 'hotfix**' 8 | 9 | concurrency: ${{ github.workflow }}-${{ github.ref }} 10 | 11 | jobs: 12 | release: 13 | name: Create version PR from release branch 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: write 17 | pull-requests: write 18 | steps: 19 | - name: Checkout Repo 20 | uses: actions/checkout@v3 21 | 22 | - name: Cache turbo build setup 23 | uses: actions/cache@v3 24 | with: 25 | path: .turbo 26 | key: ${{ runner.os }}-turbo-${{ github.sha }} 27 | restore-keys: | 28 | ${{ runner.os }}-turbo- 29 | 30 | - name: Setup Node.js 18 31 | uses: actions/setup-node@v3 32 | with: 33 | node-version: 18 34 | 35 | - name: Install Dependencies 36 | run: yarn 37 | 38 | - name: Bump Changeset Version 39 | run: yarn ver 40 | 41 | - name: Commit Changes 42 | uses: stefanzweifel/git-auto-commit-action@v4 43 | with: 44 | commit_message: 'ci: bump package version' 45 | commit_options: '--no-verify' 46 | 47 | - name: Create Release Pull Requests 48 | env: 49 | GITHUB_TOKEN: ${{ secrets.DEV_GITHUB_TOKEN }} 50 | MAIN_TITLE: 'Release: Merge to publish new version to npm' 51 | MAIN_BODY: 'Please review and merge this Pull Request. **Caution: Merge to main branch will trigger publish to npm.**' 52 | DEV_TITLE: 'Release: Merge back new version to develop' 53 | DEV_BODY: 'Merge new prod release back to develop' 54 | run: | 55 | gh pr create --title "$MAIN_TITLE" --body "$MAIN_BODY" --base main && gh pr create --title "$DEV_TITLE" --body "$DEV_BODY" --base develop 56 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/providers/types/aptos.d.ts: -------------------------------------------------------------------------------- 1 | import { BaseConfig, WalletAdapterNetwork } from '../../constants'; 2 | import BloctoProviderInterface from './blocto.d'; 3 | 4 | export { WalletAdapterNetwork } from '../../constants'; 5 | 6 | export interface SignMessagePayload { 7 | address?: boolean; 8 | application?: boolean; 9 | chainId?: boolean; 10 | message: string; 11 | nonce: string; 12 | } 13 | export interface SignMessageResponse { 14 | address?: string; 15 | application?: string; 16 | chainId?: number; 17 | fullMessage: string; 18 | message: string; 19 | nonce: string; 20 | prefix: 'APTOS'; 21 | signature: string | string[]; 22 | bitmap?: Uint8Array; 23 | } 24 | 25 | export declare interface AptosProviderConfig extends BaseConfig { 26 | // @todo: support different network 27 | chainId: number; 28 | server?: string; 29 | } 30 | 31 | export declare interface PublicAccount { 32 | address: string | null; 33 | publicKey: string[] | null; 34 | authKey: string | null; 35 | minKeysRequired?: number; 36 | } 37 | 38 | export type NetworkInfo = { 39 | api?: string; 40 | chainId?: string; 41 | name: WalletAdapterNetwork | undefined; 42 | }; 43 | 44 | export type TxOptions = { 45 | max_gas_amount?: string; 46 | gas_unit_price?: string; 47 | [key: string]: any; 48 | }; 49 | 50 | export declare interface AptosProviderInterface 51 | extends BloctoProviderInterface { 52 | publicAccount: PublicAccount; 53 | network(): Promise; 54 | connect: () => Promise; 55 | isConnected: () => Promise; 56 | signAndSubmitTransaction( 57 | transaction: any, 58 | txOptions?: TxOptions 59 | ): Promise<{ hash: HexEncodedBytes }>; 60 | signTransaction(transaction: any): Promise; 61 | signMessage(payload: SignMessagePayload): Promise; 62 | disconnect(): Promise; 63 | } 64 | -------------------------------------------------------------------------------- /packages/dappauth/test/unit/test-utils.js: -------------------------------------------------------------------------------- 1 | import { randomBytes } from 'crypto'; 2 | import { Buffer } from 'safe-buffer'; 3 | import { keccak, ecsign, toRpcSig, hashPersonalMessage, toBuffer, stripHexPrefix, bufferToHex, privateToAddress } from 'ethereumjs-util'; 4 | 5 | export function stringToHex(str) { 6 | return bufferToHex(Buffer.from(str, 'utf8')); 7 | } 8 | 9 | /** 10 | * @param {Buffer} message 11 | * @param {String} address 12 | * @returns {Buffer} 13 | */ 14 | export function generateErc191MessageHash(message, address) { 15 | const erc191Message = Buffer.concat([ 16 | Buffer.from('19', 'hex'), 17 | Buffer.from('00', 'hex'), 18 | Buffer.from(stripHexPrefix(address), 'hex'), 19 | message, 20 | ]); 21 | const r = keccak(erc191Message) 22 | return r; 23 | } 24 | 25 | 26 | /** 27 | * @param {Buffer | String} message 28 | * @param {String} key 29 | * @param {String} address 30 | * @returns {String} the address of the wallet (identity) 31 | */ 32 | export function signERC1654PersonalMessage(message, key, address) { 33 | // we hash once before erc191MessageHash as it will be transmitted to Ethereum nodes and potentially logged 34 | const messageHash = generateErc191MessageHash(keccak(toBuffer(stringToHex(message))), address); 35 | const signature = ecsign(messageHash, key); 36 | return toRpcSig(signature.v, signature.r, signature.s); 37 | } 38 | 39 | // emulates what EOA wallets like MetaMask perform 40 | export function signEOAPersonalMessage(message, key) { 41 | const messageHash = hashPersonalMessage(toBuffer(stringToHex(message))); 42 | const signature = ecsign(messageHash, key); 43 | return toRpcSig(signature.v, signature.r, signature.s); 44 | } 45 | 46 | 47 | export function generateRandomKey() { 48 | return toBuffer(`0x${randomBytes(32).toString('hex')}`); 49 | } 50 | 51 | export function keyToAddress(key) { 52 | return bufferToHex(privateToAddress(key)); 53 | } 54 | -------------------------------------------------------------------------------- /packages/dappauth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/dappauth", 3 | "version": "2.2.2", 4 | "description": "A util to prove actionable control ('ownership') over a public Ethereum address using eth_sign", 5 | "keywords": [ 6 | "ethereum", 7 | "ownership", 8 | "control", 9 | "eth_sign" 10 | ], 11 | "type": "module", 12 | "repository": "github:blocto/dappauth.js", 13 | "main": "./dist/dappauth.js", 14 | "module": "./dist/dappauth.module.js", 15 | "browser": "./dist/dappauth.umd.js", 16 | "exports": { 17 | "require": "./dist/dappauth.js", 18 | "import": "./dist/dappauth.module.js" 19 | }, 20 | "scripts": { 21 | "build": "rollup -c", 22 | "lint": "eslint --ext .js src/", 23 | "test": "jest --config=./test/unit/jest.config.cjs --coverage=true --coverage-reporters=text", 24 | "prettier:watch": "onchange '**/*.js' -- prettier --write {{changed}}" 25 | }, 26 | "author": "Pazams ", 27 | "license": "MIT", 28 | "dependencies": { 29 | "ethereumjs-abi": "^0.6.6", 30 | "ethereumjs-util": "^7.1.5", 31 | "safe-buffer": "^5.1.2", 32 | "web3": "^1.3.1" 33 | }, 34 | "devDependencies": { 35 | "@babel/core": "^7.23.6", 36 | "@babel/preset-env": "^7.23.6", 37 | "@babel/register": "^7.22.15", 38 | "@rollup/plugin-commonjs": "^25.0.4", 39 | "@rollup/plugin-node-resolve": "^15.2.1", 40 | "babel-eslint": "^8.0.1", 41 | "babel-jest": "^29.7.0", 42 | "babel-plugin-istanbul": "^6.1.1", 43 | "coveralls": "^3.0.0", 44 | "eslint": "^8.42.0", 45 | "eslint-config-prettier": "^2.9.0", 46 | "eslint-plugin-prettier": "^2.6.0", 47 | "jest": "^29.7.0", 48 | "onchange": "^7.1.0", 49 | "prettier": "^1.14.3", 50 | "rollup": "^3.29.1", 51 | "rollup-plugin-copy": "^3.5.0", 52 | "rollup-plugin-json": "^4.0.0", 53 | "rollup-plugin-node-polyfills": "^0.2.1", 54 | "rollup-plugin-terser": "^7.0.2" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/src/components/BloctoLogo.tsx: -------------------------------------------------------------------------------- 1 | const BLOCTO_LOGO = 2 | 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzIyMzNfMjM4NykiPgo8cmVjdCB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHJ4PSIxMiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTMyLjkwMjggMTguMzA2M0MyOC4zOTExIDE4LjMwNjMgMjMuOTg3MyAyMC4wNDU5IDIwLjY5NTIgMjMuMTMxOUMxNy4wODQzIDI2LjUxNzYgMTQuNzk5MiAzMS41MTc3IDEzLjQ4OTMgMzYuMjIxMkMxMi42MzE0IDM5LjI5OTIgMTIuMjAxNiA0Mi40OTE1IDEyLjIwMTYgNDUuNjg1M0MxMi4yMDE2IDQ2LjY1MTEgMTIuMjQxMiA0Ny42MDg5IDEyLjMxNzQgNDguNTU1NkMxMi40MTA5IDQ5LjcwNjkgMTMuNTMyMSA1MC41MDQ2IDE0LjY0ODUgNTAuMjAzM0MxNS42MjIyIDQ5Ljk0MTYgMTYuNjQ2NiA0OS44MDA1IDE3LjcwMjggNDkuODAwNUMxOS44NzIyIDQ5LjgwMDUgMjEuOTA1MiA1MC4zOTA0IDIzLjY0OCA1MS40MjEyQzIzLjY5MDggNTEuNDQ2NiAyMy43MzIgNTEuNDcxOSAyMy43NzQ4IDUxLjQ5NTdDMjYuNjA3MSA1My4xODQ2IDI5Ljk0ODQgNTQuMTEyMyAzMy41MTE3IDUzLjk5MzRDNDIuODA2MiA1My42ODU3IDUwLjM5OSA0Ni4xMjMgNTAuNzQxNiAzNi44MzAxQzUxLjExNTggMjYuNjYzNSA0Mi45ODY5IDE4LjMwNDcgMzIuOTA0NCAxOC4zMDQ3TDMyLjkwMjggMTguMzA2M1pNMzIuOTAyOCA0NC4zMTJDMjguMzk3NSA0NC4zMTIgMjQuNzQ1NCA0MC42NTk5IDI0Ljc0NTQgMzYuMTU2MkMyNC43NDU0IDMxLjY1MjUgMjguMzk3NSAyNy45OTg3IDMyLjkwMjggMjcuOTk4N0MzNy40MDgxIDI3Ljk5ODcgNDEuMDYwMiAzMS42NTA5IDQxLjA2MDIgMzYuMTU2MkM0MS4wNjAyIDQwLjY2MTQgMzcuNDA4MSA0NC4zMTIgMzIuOTAyOCA0NC4zMTJaIiBmaWxsPSIjMTRBQUZGIi8+CjxwYXRoIGQ9Ik0yNS41NjM2IDEyLjY4MjZDMjUuNTYzNiAxNS4wMzQ0IDI0LjMzMTUgMTcuMjE2NCAyMi4zMDggMTguNDE1M0MyMS4wMzc3IDE5LjE2ODYgMTkuODQ2OCAyMC4wNTgyIDE4Ljc2ODQgMjEuMDcxNUMxNi4zNzU1IDIzLjMxMzkgMTQuNTg5OCAyNi4wNjUzIDEzLjI2NzMgMjguNzkyOUMxMy4wMDcyIDI5LjMzMDQgMTIuMiAyOS4xNDAyIDEyLjIgMjguNTQyM1YxMi42ODI2QzEyLjIgOC45OTI0MiAxNS4xOTI0IDYgMTguODgyNiA2QzIyLjU3MjggNiAyNS41NjUyIDguOTkyNDIgMjUuNTY1MiAxMi42ODI2SDI1LjU2MzZaIiBmaWxsPSIjMDA3NUZGIi8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMjIzM18yMzg3Ij4KPHJlY3Qgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo='; 3 | 4 | export const BloctoLogo = () => ; 5 | -------------------------------------------------------------------------------- /packages/dappauth/rollup.config.js: -------------------------------------------------------------------------------- 1 | import commonjs from '@rollup/plugin-commonjs'; 2 | import resolve from '@rollup/plugin-node-resolve'; 3 | import json from 'rollup-plugin-json'; 4 | import polyfills from 'rollup-plugin-polyfill-node'; 5 | import copy from 'rollup-plugin-copy'; 6 | 7 | export default [ 8 | // CommonJS 9 | { 10 | input: 'src/index.js', 11 | output: { 12 | file: 'dist/dappauth.js', 13 | format: 'cjs', 14 | name: 'DappAuth', 15 | exports: 'auto', 16 | }, 17 | plugins: [ 18 | copy({ 19 | targets: [ 20 | { src: './src/ABIs', dest: 'dist' }, 21 | { src: './src/utils', dest: 'dist' }, 22 | ], 23 | }), 24 | commonjs(), 25 | resolve({ 26 | browser: true, 27 | preferBuiltins: true, 28 | }), 29 | json(), 30 | polyfills(), 31 | ], 32 | treeshake: { 33 | unknownGlobalSideEffects: false, 34 | }, 35 | }, 36 | // es 37 | { 38 | input: 'src/index.js', 39 | output: { 40 | file: 'dist/dappauth.module.js', 41 | format: 'es', 42 | name: 'DappAuth', 43 | }, 44 | plugins: [ 45 | copy({ 46 | targets: [ 47 | { src: './src/ABIs', dest: 'dist' }, 48 | { src: './src/utils', dest: 'dist' }, 49 | ], 50 | }), 51 | commonjs(), 52 | resolve({ 53 | browser: true, 54 | preferBuiltins: true, 55 | }), 56 | json(), 57 | polyfills(), 58 | ], 59 | }, 60 | // umd 61 | { 62 | input: 'src/index.js', 63 | output: { 64 | file: 'dist/dappauth.umd.js', 65 | format: 'umd', 66 | name: 'DappAuth', 67 | }, 68 | plugins: [ 69 | copy({ 70 | targets: [ 71 | { src: './src/ABIs', dest: 'dist' }, 72 | { src: './src/utils', dest: 'dist' }, 73 | ], 74 | }), 75 | commonjs(), 76 | resolve({ 77 | preferBuiltins: true, 78 | browser: true, 79 | }), 80 | json(), 81 | polyfills(), 82 | ], 83 | }, 84 | ]; 85 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/src/web3ModalConfig.ts: -------------------------------------------------------------------------------- 1 | const BLOCTO_LOGO = 2 | 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzIyMzNfMjM4NykiPgo8cmVjdCB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHJ4PSIxMiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTMyLjkwMjggMTguMzA2M0MyOC4zOTExIDE4LjMwNjMgMjMuOTg3MyAyMC4wNDU5IDIwLjY5NTIgMjMuMTMxOUMxNy4wODQzIDI2LjUxNzYgMTQuNzk5MiAzMS41MTc3IDEzLjQ4OTMgMzYuMjIxMkMxMi42MzE0IDM5LjI5OTIgMTIuMjAxNiA0Mi40OTE1IDEyLjIwMTYgNDUuNjg1M0MxMi4yMDE2IDQ2LjY1MTEgMTIuMjQxMiA0Ny42MDg5IDEyLjMxNzQgNDguNTU1NkMxMi40MTA5IDQ5LjcwNjkgMTMuNTMyMSA1MC41MDQ2IDE0LjY0ODUgNTAuMjAzM0MxNS42MjIyIDQ5Ljk0MTYgMTYuNjQ2NiA0OS44MDA1IDE3LjcwMjggNDkuODAwNUMxOS44NzIyIDQ5LjgwMDUgMjEuOTA1MiA1MC4zOTA0IDIzLjY0OCA1MS40MjEyQzIzLjY5MDggNTEuNDQ2NiAyMy43MzIgNTEuNDcxOSAyMy43NzQ4IDUxLjQ5NTdDMjYuNjA3MSA1My4xODQ2IDI5Ljk0ODQgNTQuMTEyMyAzMy41MTE3IDUzLjk5MzRDNDIuODA2MiA1My42ODU3IDUwLjM5OSA0Ni4xMjMgNTAuNzQxNiAzNi44MzAxQzUxLjExNTggMjYuNjYzNSA0Mi45ODY5IDE4LjMwNDcgMzIuOTA0NCAxOC4zMDQ3TDMyLjkwMjggMTguMzA2M1pNMzIuOTAyOCA0NC4zMTJDMjguMzk3NSA0NC4zMTIgMjQuNzQ1NCA0MC42NTk5IDI0Ljc0NTQgMzYuMTU2MkMyNC43NDU0IDMxLjY1MjUgMjguMzk3NSAyNy45OTg3IDMyLjkwMjggMjcuOTk4N0MzNy40MDgxIDI3Ljk5ODcgNDEuMDYwMiAzMS42NTA5IDQxLjA2MDIgMzYuMTU2MkM0MS4wNjAyIDQwLjY2MTQgMzcuNDA4MSA0NC4zMTIgMzIuOTAyOCA0NC4zMTJaIiBmaWxsPSIjMTRBQUZGIi8+CjxwYXRoIGQ9Ik0yNS41NjM2IDEyLjY4MjZDMjUuNTYzNiAxNS4wMzQ0IDI0LjMzMTUgMTcuMjE2NCAyMi4zMDggMTguNDE1M0MyMS4wMzc3IDE5LjE2ODYgMTkuODQ2OCAyMC4wNTgyIDE4Ljc2ODQgMjEuMDcxNUMxNi4zNzU1IDIzLjMxMzkgMTQuNTg5OCAyNi4wNjUzIDEzLjI2NzMgMjguNzkyOUMxMy4wMDcyIDI5LjMzMDQgMTIuMiAyOS4xNDAyIDEyLjIgMjguNTQyM1YxMi42ODI2QzEyLjIgOC45OTI0MiAxNS4xOTI0IDYgMTguODgyNiA2QzIyLjU3MjggNiAyNS41NjUyIDguOTkyNDIgMjUuNTY1MiAxMi42ODI2SDI1LjU2MzZaIiBmaWxsPSIjMDA3NUZGIi8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMjIzM18yMzg3Ij4KPHJlY3Qgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo='; 3 | 4 | const bloctoWeb3ModalConfig = { 5 | walletImages: { 6 | blocto: BLOCTO_LOGO, 7 | }, 8 | }; 9 | 10 | export default bloctoWeb3ModalConfig; 11 | -------------------------------------------------------------------------------- /packages/dappauth/test/unit/contract-mock.js: -------------------------------------------------------------------------------- 1 | import { fromRpcSig, ecrecover, publicToAddress } from 'ethereumjs-util'; 2 | import abi from 'ethereumjs-abi'; 3 | import { Buffer } from 'safe-buffer'; 4 | import { generateErc191MessageHash } from './test-utils.js'; 5 | 6 | const { rawDecode } = abi; 7 | // bytes4(keccak256("isValidSignature(bytes32,bytes)") 8 | const ERC1271_METHOD_SIG = '1626ba7e'; 9 | 10 | export default class MockContract { 11 | constructor(options) { 12 | this.authorizedKey = options.authorizedKey; 13 | this.address = options.address; 14 | this.errorIsValidSignature = options.errorIsValidSignature; 15 | } 16 | 17 | static _true() { 18 | return `0x${ERC1271_METHOD_SIG}00000000000000000000000000000000000000000000000000000000`; // a.k.a the "magic value". 19 | } 20 | 21 | static _false() { 22 | return '0x0000000000000000000000000000000000000000000000000000000000000000'; 23 | } 24 | 25 | // @param {String} methodCall 26 | // @param {String} methodParams 27 | // @return {String} 28 | run(methodCall, methodParams) { 29 | switch (methodCall) { 30 | case ERC1271_METHOD_SIG: { 31 | const [hash, signature] = rawDecode( 32 | ['bytes32', 'bytes'], 33 | Buffer.from(methodParams, 'hex'), 34 | ); 35 | return this._1626ba7e(hash, signature); 36 | } 37 | default: 38 | throw new Error(`Unexpected method ${methodCall}`); 39 | } 40 | } 41 | 42 | // "isValidSignature" method call 43 | // @param {Buffer} hash 44 | // @param {Buffer} signature 45 | // @return {String} 46 | _1626ba7e(hash, signature) { 47 | if (this.errorIsValidSignature) { 48 | throw new Error('isValidSignature call returned an error'); 49 | } 50 | // split to 65 bytes (130 hex) chunks 51 | const multi_sigs = signature.toString('hex').match(/.{1,130}/g); 52 | 53 | // TODO: is it first or last? 54 | const expected_authrorised_sig = multi_sigs[0]; 55 | 56 | // Get the address of whoever signed this message 57 | const { v, r, s } = fromRpcSig(`0x${expected_authrorised_sig}`); 58 | const erc191MessageHash = generateErc191MessageHash(hash, this.address); 59 | const recoveredKey = ecrecover(erc191MessageHash, v, r, s); 60 | const recoveredAddress = publicToAddress(recoveredKey); 61 | 62 | const expectedAddress = publicToAddress(this.authorizedKey); 63 | 64 | if (recoveredAddress.toString() === expectedAddress.toString()) { 65 | return MockContract._true(); 66 | } 67 | 68 | return MockContract._false(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/dappauth/src/index.js: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3'; 2 | import { fromRpcSig, ecrecover, publicToAddress, bufferToHex, hashPersonalMessage, keccak } from 'ethereumjs-util'; 3 | import ERC1271 from './ABIs/ERC1271.js'; 4 | import { mergeErrors, isHexString, removeHexPrefix } from './utils/index.js'; 5 | 6 | // bytes4(keccak256("isValidSignature(bytes32,bytes)") 7 | const ERC1271_MAGIC_VALUE = '0x1626ba7e'; 8 | 9 | export default class DappAuth { 10 | constructor(web3Provider) { 11 | this.web3 = new Web3(web3Provider); 12 | } 13 | 14 | async isAuthorizedSigner(challenge, signature, address) { 15 | const eoaChallengeHash = this._hashEOAPersonalMessage(challenge); 16 | let isAuthorizedDirectKey; 17 | let errEOA; 18 | 19 | // try direct-keyed wallet 20 | try { 21 | // Get the address of whoever signed this message 22 | const { v, r, s } = fromRpcSig(signature); 23 | const recoveredKey = ecrecover(eoaChallengeHash, v, r, s); 24 | const recoveredAddress = publicToAddress(recoveredKey); 25 | 26 | if ( 27 | address.toLowerCase() === 28 | bufferToHex(recoveredAddress).toLowerCase() 29 | ) { 30 | isAuthorizedDirectKey = true; 31 | } 32 | } catch (err) { 33 | errEOA = err; 34 | // if either direct-keyed auth flow threw an error, or it did not conclude to be authorized, proceed to try smart-contract wallet. 35 | } 36 | try { 37 | if (isAuthorizedDirectKey === true) return isAuthorizedDirectKey; 38 | // try smart-contract wallet 39 | const erc1271CoreContract = new this.web3.eth.Contract(ERC1271, address); 40 | 41 | // check persoonalSign hash first 42 | const magicValue = await erc1271CoreContract.methods 43 | .isValidSignature(eoaChallengeHash, signature) 44 | .call(); 45 | if (magicValue === ERC1271_MAGIC_VALUE) { 46 | return true; 47 | } else { 48 | // then check SCMessage hash (ERC-1654) 49 | const magicValue2 = await erc1271CoreContract.methods 50 | .isValidSignature(this._hashSCMessage(challenge), signature) 51 | .call(); 52 | 53 | return magicValue2 === ERC1271_MAGIC_VALUE; 54 | } 55 | } catch (err) { 56 | throw mergeErrors(errEOA, err); 57 | } 58 | } 59 | 60 | _hashEOAPersonalMessage(challenge) { 61 | return hashPersonalMessage(this._decodeChallenge(challenge)); 62 | } 63 | 64 | // This is a hash just over the challenge. The smart contract takes this result and hashes on top to an erc191 hash. 65 | _hashSCMessage(challenge) { 66 | return keccak(this._decodeChallenge(challenge)); 67 | } 68 | 69 | // See https://github.com/MetaMask/eth-sig-util/issues/60 70 | _decodeChallenge(challenge) { 71 | return isHexString(challenge) 72 | ? Buffer.from(removeHexPrefix(challenge), 'hex') 73 | : Buffer.from(challenge); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /packages/blocto-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blocto/sdk", 3 | "version": "0.10.4", 4 | "repository": "git@github.com:portto/blocto-sdk.git", 5 | "author": "Chiaki.C", 6 | "license": "MIT", 7 | "main": "dist/blocto-sdk.js", 8 | "module": "dist/blocto-sdk.module.js", 9 | "browser": "dist/blocto-sdk.umd.js", 10 | "types": "dist/blocto-sdk.d.ts", 11 | "type": "module", 12 | "exports": { 13 | "require": "./dist/blocto-sdk.js", 14 | "import": "./dist/blocto-sdk.module.js", 15 | "types": "./dist/blocto-sdk.d.ts" 16 | }, 17 | "files": [ 18 | "/dist/**/!(*.html)" 19 | ], 20 | "scripts": { 21 | "build": "NODE_ENV=production rollup -c", 22 | "clean": "rimraf dist", 23 | "lint": "eslint --ext .js,.ts src/", 24 | "test": "jest", 25 | "prepublishOnly": "npm-run-all clean build", 26 | "rollup-watch": "NODE_ENV=development rollup -c rollup.config.dev.js --watch", 27 | "serve": "live-server --port=7777 --https=dev-cert/index.js dev", 28 | "start": "npm-run-all --parallel rollup-watch serve" 29 | }, 30 | "dependencies": { 31 | "buffer": "^6.0.3", 32 | "eip1193-provider": "^1.0.1", 33 | "js-sha3": "^0.8.0" 34 | }, 35 | "devDependencies": { 36 | "@babel/core": "^7.22.1", 37 | "@babel/eslint-parser": "^7.21.8", 38 | "@babel/eslint-plugin": "^7.14.5", 39 | "@babel/plugin-transform-runtime": "^7.22.4", 40 | "@babel/preset-env": "^7.22.4", 41 | "@babel/runtime": "^7.22.3", 42 | "@rollup/plugin-alias": "^5.0.0", 43 | "@rollup/plugin-babel": "^6.0.3", 44 | "@rollup/plugin-commonjs": "^25.0.0", 45 | "@rollup/plugin-node-resolve": "^15.1.0", 46 | "@rollup/plugin-typescript": "^11.1.1", 47 | "@types/jest": "^29.5.2", 48 | "@typescript-eslint/eslint-plugin": "^5.59.9", 49 | "@typescript-eslint/parser": "^5.59.9", 50 | "aptos": "^1.15.0", 51 | "babel-jest": "^29.5.0", 52 | "babel-plugin-module-resolver": "^5.0.0", 53 | "eslint": "^8.42.0", 54 | "eslint-import-resolver-babel-module": "^5.3.1", 55 | "eslint-plugin-import": "^2.23.4", 56 | "eth-rpc-errors": "^4.0.3", 57 | "jest": "^29.5.0", 58 | "jest-environment-jsdom": "^29.5.0", 59 | "jest-fetch-mock": "^3.0.3", 60 | "live-server": "^1.2.1", 61 | "rimraf": "^5.0.1", 62 | "rollup": "^3.23.1", 63 | "rollup-plugin-dts": "^5.3.0", 64 | "rollup-plugin-json": "^4.0.0", 65 | "rollup-plugin-peer-deps-external": "^2.2.4", 66 | "rollup-plugin-polyfill-node": "^0.12.0", 67 | "rollup-plugin-terser": "^7.0.2", 68 | "rollup-plugin-version-injector": "^1.3.3", 69 | "rollup-plugin-visualizer": "^5.5.4", 70 | "ts-jest": "^29.1.0", 71 | "tslib": "^2.5.3", 72 | "typescript": "~5.1.3", 73 | "yarn-run-all": "^3.1.1" 74 | }, 75 | "peerDependencies": { 76 | "aptos": "^1.3.14" 77 | }, 78 | "peerDependenciesMeta": { 79 | "aptos": { 80 | "optional": true 81 | } 82 | }, 83 | "keywords": [ 84 | "portto", 85 | "blocto", 86 | "ethereum", 87 | "aptos", 88 | "wallet", 89 | "sdk", 90 | "web3", 91 | "web3.js", 92 | "javascript", 93 | "typescript", 94 | "dapp", 95 | "react", 96 | "vue" 97 | ] 98 | } 99 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/__tests__/isValidTransaction.test.js: -------------------------------------------------------------------------------- 1 | import { isValidTransaction, isValidTransactions } from "../lib/isValidTransaction"; 2 | import { ERROR_MESSAGE } from "../lib/constant"; 3 | 4 | describe("isValidTransaction", () => { 5 | it("should return valid when passing valid transaction", () => { 6 | const mockTransaction = { 7 | from: "0xC5a6382a81CDA092DBdE9dFeEfa2642306cF0006", 8 | to: "0x509Ee0d083DdF8AC028f2a56731412edD63223B9", 9 | value: "0x1" 10 | } 11 | 12 | expect(isValidTransaction(mockTransaction)).toEqual({ isValid: true }); 13 | }); 14 | 15 | it("should return invalid when passing invalid transaction without 'from'", () => { 16 | const mockTransaction = { 17 | to: "0x509Ee0d083DdF8AC028f2a56731412edD63223B9", 18 | value: "0x1" 19 | }; 20 | 21 | expect(isValidTransaction(mockTransaction)).toEqual({ isValid: false, invalidMsg: ERROR_MESSAGE.INVALID_TRANSACTION }); 22 | }); 23 | 24 | it("should return invalid when passing transaction with invalid 'value'", () => { 25 | const mockTransaction = { 26 | from: "0xC5a6382a81CDA092DBdE9dFeEfa2642306cF0006", 27 | to: "0x509Ee0d083DdF8AC028f2a56731412edD63223B9", 28 | value: 1 29 | }; 30 | 31 | expect(isValidTransaction(mockTransaction)).toEqual({ isValid: false, invalidMsg: ERROR_MESSAGE.INVALID_TRANSACTION_VALUE }); 32 | }); 33 | }); 34 | 35 | describe("isValidTransactions", () => { 36 | it("should return valid for an array of valid transactions", () => { 37 | const mockTransactions = [ 38 | { 39 | from: "0xC5a6382a81CDA092DBdE9dFeEfa2642306cF0006", 40 | to: "0x509Ee0d083DdF8AC028f2a56731412edD63223B9", 41 | value: "0x1" 42 | }, 43 | { 44 | from: "0xC5a6382a81CDA092DBdE9dFeEfa2642306cF0006", 45 | to: "0x509Ee0d083DdF8AC028f2a56731412edD63223B9", 46 | data: "0xa9059cbb00000000000000000000000076c7a9cac72db4865bd1db3acfa78a261755c4fb0000000000000000000000000000000000000000000000000000000005f5e100", 47 | } 48 | ]; 49 | 50 | expect(isValidTransactions(mockTransactions)).toEqual({ isValid: true }); 51 | }); 52 | 53 | it("should return invalid when passing invalid array of transactions", () => { 54 | const mockTransactions = "notAnArray"; 55 | 56 | expect(isValidTransactions(mockTransactions)).toEqual({ isValid: false, invalidMsg: ERROR_MESSAGE.INVALID_TRANSACTIONS }); 57 | }); 58 | 59 | it("should return invalid when passing contain invalid transactions", () => { 60 | const mockTransactions = [ 61 | { 62 | from: "0xC5a6382a81CDA092DBdE9dFeEfa2642306cF0006", 63 | to: "0x509Ee0d083DdF8AC028f2a56731412edD63223B9", 64 | value: 1 65 | }, 66 | { 67 | from: "0xC5a6382a81CDA092DBdE9dFeEfa2642306cF0006", 68 | to: "0x509Ee0d083DdF8AC028f2a56731412edD63223B9", 69 | data: "0xa9059cbb000000000000000000000000d3ea1bfe3d1f99278c2ac7b6429e2e2ac32564e30000000000000000000000000000000000000000000000000000000005f5e100", 70 | } 71 | ]; 72 | 73 | expect(isValidTransactions(mockTransactions)).toEqual({ isValid: false, invalidMsg: ERROR_MESSAGE.INVALID_TRANSACTION_VALUE }); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /adapters/rainbowkit-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Wallet, WalletDetailsParams } from '@rainbow-me/rainbowkit'; 2 | import { blocto, createConnector } from '@blocto/wagmi-connector'; 3 | 4 | export const bloctoWallet = 5 | ({ appId }: { appId?: string } = {}) => 6 | (): Wallet => { 7 | return { 8 | id: 'blocto', 9 | name: 'Blocto', 10 | shortName: 'Blocto', 11 | rdns: 'io.blocto', 12 | iconBackground: '#ffffff', 13 | iconUrl: 14 | 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjhweCIgaGVpZ2h0PSIyOHB4IiB2aWV3Qm94PSIwIDAgMjggMjgiIHZlcnNpb249IjEuMSI+CjxnIGlkPSJzdXJmYWNlMSI+CjxyZWN0IHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgZmlsbD0id2hpdGUiLz4KPHBhdGggc3R5bGU9IiBzdHJva2U6bm9uZTtmaWxsLXJ1bGU6bm9uemVybztmaWxsOnJnYig3Ljg0MzEzNyUsNjYuNjY2NjY3JSwxMDAlKTtmaWxsLW9wYWNpdHk6MTsiIGQ9Ik0gMTUuMzU1NDY5IDguNTQyOTY5IEMgMTMuMjUgOC41NDI5NjkgMTEuMTk1MzEyIDkuMzU1NDY5IDkuNjU2MjUgMTAuNzkyOTY5IEMgNy45NzI2NTYgMTIuMzc1IDYuOTA2MjUgMTQuNzA3MDMxIDYuMjk2ODc1IDE2LjkwMjM0NCBDIDUuODk0NTMxIDE4LjMzOTg0NCA1LjY5NTMxMiAxOS44MjgxMjUgNS42OTUzMTIgMjEuMzIwMzEyIEMgNS42OTUzMTIgMjEuNzY5NTMxIDUuNzEwOTM4IDIyLjIxODc1IDUuNzUgMjIuNjYwMTU2IEMgNS43OTI5NjkgMjMuMTk1MzEyIDYuMzE2NDA2IDIzLjU3MDMxMiA2LjgzNTkzOCAyMy40Mjk2ODggQyA3LjI4OTA2MiAyMy4zMDQ2ODggNy43Njk1MzEgMjMuMjM4MjgxIDguMjYxNzE5IDIzLjIzODI4MSBDIDkuMjczNDM4IDIzLjIzODI4MSAxMC4yMjI2NTYgMjMuNTE1NjI1IDExLjAzNTE1NiAyMy45OTYwOTQgQyAxMS4wNTQ2ODggMjQuMDA3ODEyIDExLjA3NDIxOSAyNC4wMTk1MzEgMTEuMDkzNzUgMjQuMDMxMjUgQyAxMi40MTc5NjkgMjQuODIwMzEyIDEzLjk3NjU2MiAyNS4yNTM5MDYgMTUuNjQwNjI1IDI1LjE5NTMxMiBDIDE5Ljk3NjU2MiAyNS4wNTQ2ODggMjMuNTE5NTMxIDIxLjUyMzQzOCAyMy42Nzk2ODggMTcuMTg3NSBDIDIzLjg1NTQ2OSAxMi40NDE0MDYgMjAuMDYyNSA4LjU0Mjk2OSAxNS4zNTU0NjkgOC41NDI5NjkgWiBNIDE1LjM1NTQ2OSAyMC42Nzk2ODggQyAxMy4yNTM5MDYgMjAuNjc5Njg4IDExLjU0Njg3NSAxOC45NzY1NjIgMTEuNTQ2ODc1IDE2Ljg3MTA5NCBDIDExLjU0Njg3NSAxNC43Njk1MzEgMTMuMjUzOTA2IDEzLjA2NjQwNiAxNS4zNTU0NjkgMTMuMDY2NDA2IEMgMTcuNDU3MDMxIDEzLjA2NjQwNiAxOS4xNjAxNTYgMTQuNzY5NTMxIDE5LjE2MDE1NiAxNi44NzEwOTQgQyAxOS4xNjAxNTYgMTguOTc2NTYyIDE3LjQ1NzAzMSAyMC42Nzk2ODggMTUuMzU1NDY5IDIwLjY3OTY4OCBaIE0gMTUuMzU1NDY5IDIwLjY3OTY4OCAiLz4KPHBhdGggc3R5bGU9IiBzdHJva2U6bm9uZTtmaWxsLXJ1bGU6bm9uemVybztmaWxsOnJnYigwJSw0NS44ODIzNTMlLDEwMCUpO2ZpbGwtb3BhY2l0eToxOyIgZD0iTSAxMS45Mjk2ODggNS45MTc5NjkgQyAxMS45Mjk2ODggNy4wMTU2MjUgMTEuMzU1NDY5IDguMDM1MTU2IDEwLjQxMDE1NiA4LjU5Mzc1IEMgOS44MTY0MDYgOC45NDUzMTIgOS4yNjE3MTkgOS4zNTkzNzUgOC43NTc4MTIgOS44MzIwMzEgQyA3LjY0MDYyNSAxMC44Nzg5MDYgNi44MDg1OTQgMTIuMTY0MDYyIDYuMTkxNDA2IDEzLjQzNzUgQyA2LjA3MDMxMiAxMy42ODc1IDUuNjkxNDA2IDEzLjU5NzY1NiA1LjY5MTQwNiAxMy4zMjAzMTIgTCA1LjY5MTQwNiA1LjkxNzk2OSBDIDUuNjkxNDA2IDQuMTk1MzEyIDcuMDg5ODQ0IDIuODAwNzgxIDguODEyNSAyLjgwMDc4MSBDIDEwLjUzNTE1NiAyLjgwMDc4MSAxMS45Mjk2ODggNC4xOTUzMTIgMTEuOTI5Njg4IDUuOTE3OTY5IFogTSAxMS45Mjk2ODggNS45MTc5NjkgIi8+CjwvZz4KPC9zdmc+Cg==', 15 | downloadUrls: { 16 | ios: 'https://apps.apple.com/app/blocto/id1481181682', 17 | android: 18 | 'https://play.google.com/store/apps/details?id=com.portto.blocto', 19 | }, 20 | installed: true, 21 | createConnector: (walletDetails: WalletDetailsParams) => 22 | createConnector((config) => ({ 23 | ...blocto({ appId })(config), 24 | ...walletDetails, 25 | })), 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /packages/blocto-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Blocto JavaScript SDK 2 | 3 | [![npm (lastest)](https://img.shields.io/npm/v/@blocto/sdk/latest)](https://www.npmjs.com/package/@blocto/sdk) 4 | [![npm (beta)](https://img.shields.io/npm/v/@blocto/sdk/beta)](https://www.npmjs.com/package/@blocto/sdk) 5 | [![npm bundle size](https://img.shields.io/bundlephobia/minzip/@blocto/sdk)](https://www.npmjs.com/package/@blocto/sdk) 6 | [![Github Checks](https://github.com/portto/blocto-sdk/actions/workflows/test.yml/badge.svg)](https://github.com/portto/blocto-sdk/actions/workflows/test.yml) 7 | [![npm downloads](https://img.shields.io/npm/dw/@blocto/sdk)](https://www.npmjs.com/package/@blocto/sdk) 8 | [![LICENSE](https://img.shields.io/github/license/portto/blocto-sdk)](https://github.com/portto/blocto-sdk/blob/main/LICENSE) 9 | [![Discord](https://img.shields.io/discord/720454370650619984.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.com/invite/QRZTr6yHmY) 10 | 11 | Use Blocto SDK in your dApp to provide excellent user experience! 12 | 13 | ## Looking for the documentation? 14 | 15 | [https://docs.blocto.app/blocto-sdk/javascript-sdk](https://docs.blocto.app/blocto-sdk/javascript-sdk) 16 | 17 | ## What can I do with Blocto SDK? 18 | 19 | - Interact with multiple blockchains 20 | - Interact with Ethereum-compatible blockchains 21 | Ethereum Mainnet & Goerli Testnet 22 | Arbitrum Mainnet & Arbitrum Goerli Testnet 23 | Optimism Mainnet & Optimism Goerli Testnet 24 | Polygon Mainnet & Testnet 25 | BNB Smart Chain Mainnet & Tetsnet 26 | Avalanche Mainnet & Testnet 27 | - Interact with Aptos 28 | - Sign messages 29 | - Send transactions 30 | - ... and a lot more 31 | - Seamless onboarding experience 32 | Users can sign up easily with email and start exploring you dApp in seconds. 33 | - Fee subsidization 34 | You have the option to pay transaction fee for your users and provide a better experience. In that case, we will generate daily fee reports for you to review. 35 | - Integrated payment 36 | Get paid easily with our payment APIs. Users can pay easily with credit cards or other crypto currencies like Bitcoin, Ethereum, Tron, USDT, ... 37 | - Connected to Blocto App 38 | Once you've integrated with Blocto SDK, your users can manage their assets easily and securely through Blocto App. Your dApp can tap into the vast blockchain ecosystem instantly. 39 | 40 | ## Installing 41 | 42 | ```bash 43 | $ yarn add @blocto/sdk 44 | # or 45 | $ npm i @blocto/sdk 46 | ``` 47 | 48 | ## Usage 49 | 50 | ```ts 51 | import BloctoSDK from '@blocto/sdk'; 52 | 53 | const bloctoSDK = new BloctoSDK({ 54 | // advance settings please refer to docs 55 | ethereum: { 56 | // (required) chainId to be used 57 | chainId: '0x5', 58 | // (required for Ethereum) JSON RPC endpoint 59 | rpc: 'https://mainnet.infura.io/v3/YOUR_INFURA_ID', 60 | }, 61 | 62 | // (optional) Blocto app ID 63 | appId: 'YOUR_BLOCTO_APP_ID', 64 | }); 65 | ``` 66 | 67 | ## Testing on local 68 | 69 | ``` 70 | yarn 71 | 72 | # generate local https cert 73 | brew install mkcert 74 | mkcert -install 75 | cd dev-cert 76 | mkcert localhost 77 | 78 | # make dev directory 79 | mkdir dev 80 | ln -s src/main.js dev/main.js 81 | ``` 82 | 83 | ## Scripts 84 | 85 | `build`: build dist 86 | `start`: run live-reload dev server on `https://localhost:7777` 87 | 88 | ## Develop 89 | 90 | open browser and navigate to `https://localhost:7777/test.html` 91 | -------------------------------------------------------------------------------- /packages/blocto-sdk/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { terser } from 'rollup-plugin-terser'; 2 | import { visualizer } from 'rollup-plugin-visualizer'; 3 | import typescript from '@rollup/plugin-typescript'; 4 | import commonjs from '@rollup/plugin-commonjs'; 5 | import resolve from '@rollup/plugin-node-resolve'; 6 | import json from 'rollup-plugin-json'; 7 | import polyfills from 'rollup-plugin-polyfill-node'; 8 | import alias from '@rollup/plugin-alias'; 9 | import { babel } from '@rollup/plugin-babel'; 10 | import dts from 'rollup-plugin-dts'; 11 | import peerDepsExternal from 'rollup-plugin-peer-deps-external'; 12 | import versionInjector from 'rollup-plugin-version-injector'; 13 | 14 | export default [ 15 | // CommonJS 16 | { 17 | input: 'src/main.ts', 18 | output: { 19 | file: 'dist/blocto-sdk.js', 20 | format: 'cjs', 21 | name: 'BloctoSDK', 22 | exports: 'auto', 23 | }, 24 | plugins: [ 25 | versionInjector(), 26 | alias({ 27 | entries: { 28 | 'readable-stream': 'stream', 29 | }, 30 | }), 31 | peerDepsExternal(), 32 | resolve({ 33 | preferBuiltins: true, 34 | browser: true, 35 | }), 36 | typescript(), 37 | commonjs(), 38 | json(), 39 | babel({ 40 | babelHelpers: 'runtime', 41 | exclude: 'node_modules/**', 42 | plugins: [['@babel/plugin-transform-runtime']], 43 | presets: [['@babel/preset-env']], 44 | }), 45 | polyfills(), 46 | visualizer({ filename: 'dist/stats.cjs.html' }), 47 | ], 48 | }, 49 | // es 50 | { 51 | input: 'src/main.ts', 52 | output: { 53 | file: 'dist/blocto-sdk.module.js', 54 | format: 'es', 55 | name: 'BloctoSDK', 56 | }, 57 | plugins: [ 58 | versionInjector(), 59 | alias({ 60 | entries: { 61 | 'readable-stream': 'stream', 62 | }, 63 | }), 64 | peerDepsExternal(), 65 | resolve({ 66 | preferBuiltins: true, 67 | browser: true, 68 | }), 69 | typescript(), 70 | commonjs(), 71 | json(), 72 | babel({ 73 | babelHelpers: 'runtime', 74 | exclude: 'node_modules/**', 75 | plugins: [['@babel/plugin-transform-runtime']], 76 | presets: [['@babel/preset-env']], 77 | }), 78 | polyfills(), 79 | visualizer({ filename: 'dist/stats.es.html' }), 80 | ], 81 | }, 82 | // umd 83 | { 84 | input: 'src/main.ts', 85 | output: { 86 | file: 'dist/blocto-sdk.umd.js', 87 | format: 'umd', 88 | name: 'BloctoSDK', 89 | }, 90 | plugins: [ 91 | versionInjector(), 92 | alias({ 93 | entries: { 94 | 'readable-stream': 'stream', 95 | }, 96 | }), 97 | resolve({ 98 | preferBuiltins: true, 99 | browser: true, 100 | }), 101 | typescript(), 102 | commonjs(), 103 | json(), 104 | babel({ 105 | babelHelpers: 'bundled', 106 | exclude: 'node_modules/**', 107 | presets: [['@babel/preset-env']], 108 | }), 109 | polyfills(), 110 | terser(), 111 | visualizer({ filename: 'dist/stats.umd.html' }), 112 | ], 113 | }, 114 | { 115 | input: './src/index.d.ts', 116 | output: [{ file: 'dist/blocto-sdk.d.ts', format: 'es' }], 117 | plugins: [dts()], 118 | }, 119 | ]; 120 | -------------------------------------------------------------------------------- /adapters/web3-react-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | Actions, 3 | AddEthereumChainParameter, 4 | ProviderConnectInfo, 5 | ProviderRpcError, 6 | } from '@web3-react/types'; 7 | import { Connector } from '@web3-react/types'; 8 | import BloctoSDK from '@blocto/sdk'; 9 | 10 | function parseChainId(chainId: string | number): number { 11 | return typeof chainId === 'number' 12 | ? chainId 13 | : Number.parseInt(chainId, chainId.startsWith('0x') ? 16 : 10); 14 | } 15 | 16 | /** 17 | * @param options - Options to pass to Blocto SDK. 18 | * @param onError - Handler to report errors thrown from eventListeners. 19 | */ 20 | type BloctoOptions = { 21 | chainId: number; 22 | rpc: string; 23 | }; 24 | 25 | export interface BloctoConstructorArgs { 26 | actions: Actions; 27 | options: BloctoOptions; 28 | onError?: (error: Error) => void; 29 | } 30 | 31 | export class BloctoConnector extends Connector { 32 | public provider: any; 33 | 34 | constructor({ actions, options, onError }: BloctoConstructorArgs) { 35 | super(actions, onError); 36 | const bloctoSDK = new BloctoSDK({ 37 | ethereum: { 38 | chainId: options.chainId, 39 | rpc: options.rpc, 40 | }, 41 | }); 42 | 43 | this.provider = bloctoSDK.ethereum; 44 | 45 | this.provider.on( 46 | 'connect', 47 | async ({ chainId }: ProviderConnectInfo): Promise => { 48 | const accounts = await this.provider.request({ 49 | method: 'eth_requestAccounts', 50 | }); 51 | this.actions.update({ chainId: parseChainId(chainId), accounts }); 52 | } 53 | ); 54 | this.provider.on('disconnect', (error: ProviderRpcError): void => { 55 | this.actions.resetState(); 56 | this.onError?.(error); 57 | }); 58 | this.provider.on('chainChanged', async (chainId: string): Promise => { 59 | const accounts = await this.provider.request({ 60 | method: 'eth_requestAccounts', 61 | }); 62 | this.actions.update({ chainId: parseChainId(chainId), accounts }); 63 | }); 64 | } 65 | 66 | public async activate( 67 | desiredChainIdOrChainParameters?: number | AddEthereumChainParameter 68 | ): Promise { 69 | const desiredChainId = 70 | typeof desiredChainIdOrChainParameters === 'number' 71 | ? desiredChainIdOrChainParameters 72 | : desiredChainIdOrChainParameters?.chainId; 73 | 74 | if (!this.provider) throw new Error('No provider'); 75 | if ( 76 | !desiredChainId || 77 | parseChainId(desiredChainId) === parseChainId(this.provider.chainId) 78 | ) { 79 | const accounts = await this.provider.request({ 80 | method: 'eth_requestAccounts', 81 | }); 82 | 83 | return this.actions.update({ 84 | chainId: parseChainId(this.provider.chainId), 85 | accounts, 86 | }); 87 | } 88 | const addEthereumChainParameters = 89 | typeof desiredChainIdOrChainParameters === 'number' 90 | ? { chainId: desiredChainId } 91 | : desiredChainIdOrChainParameters; 92 | 93 | await this.provider.request({ 94 | method: 'wallet_addEthereumChain', 95 | params: [addEthereumChainParameters], 96 | }); 97 | await this.provider.request({ 98 | method: 'wallet_switchEthereumChain', 99 | params: [{ chainId: desiredChainId }], 100 | }); 101 | } 102 | 103 | public deactivate(): void { 104 | this.provider.request({ method: 'wallet_disconnect' }); 105 | this.actions.resetState(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Blocto JavaScript SDK 2 | 3 | Thanks for showing interest to contribute to Blocto JavaScript SDK, you rock! 4 | 5 | ## When it comes to open source, there are different ways you can contribute, all of which are valuable. Here's a few guidelines that should help you as you prepare your contribution. 6 | 7 | ## Setup the Project 8 | 9 | The following steps will get you up and running to contribute to Chakra UI: 10 | 11 | 1. Fork the repo (click the Fork button at the top right of 12 | [this page](https://github.com/portto/blocto-sdk)) 13 | 14 | 2. Clone your fork locally 15 | 16 | ```sh 17 | git clone https://github.com//blocto-sdk.git 18 | cd blocto-sdk 19 | ``` 20 | 21 | 3. Setup all the dependencies and packages by running `yarn`. This 22 | command will install dependencies. 23 | 24 | ## Development 25 | 26 | To improve our development process, we've set up tooling and systems. Blocto JavaScript SDK is a monorepo built with [turbo](https://turbo.build/repo/docs) and follows its file structure convention. The repo has 2 workspaces `adapters` and `packages`. 27 | 28 | ### Commit Convention 29 | 30 | Before you create a Pull Request, please check whether your commits comply with 31 | the commit conventions used in this repository. 32 | 33 | When you create a commit we kindly ask you to follow the convention 34 | `category(scope or module): message` in your commit message while using one of 35 | the following categories: 36 | 37 | - `feat`: all changes that introduce completely new code or new 38 | features 39 | - `fix`: changes that fix a bug (ideally you will additionally reference an 40 | issue if present) 41 | - `refactor`: any code related change that is not a fix nor a feature 42 | - `docs`: changing existing or creating new documentation (i.e. README, docs for 43 | usage of a lib or cli usage) 44 | - `build`: all changes regarding the build of the software, changes to 45 | dependencies or the addition of new dependencies 46 | - `test`: all changes regarding tests (adding new tests or changing existing 47 | ones) 48 | - `ci`: all changes regarding the configuration of continuous integration (i.e. 49 | github actions, ci system) 50 | - `chore`: all changes to the repository that do not fit into any of the above 51 | categories 52 | 53 | If you are interested in the detailed specification you can visit 54 | https://www.conventionalcommits.org/ or check out the 55 | [Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines). 56 | 57 | ### Creating a Pull Request 58 | 59 | You are welcome to create a pull reuqest against the `develop` branch. The beta release channel goes here. When it's stable, we will pack it all and release in stable channel. 60 | 61 | Before creating a PR 62 | 63 | 1. Make sure your branch is up to date with the `develop` branch 64 | 2. On the `root` folder, run `yarn` 65 | 3. On the `root` folder, run `yarn build` 66 | 4. If a pull request created needs to bump a package version, please see [Changesets](#Changesets) part and add a changesets. 67 | 68 | If everything passes, you should be able to create a PR. 69 | 70 | #### Changesets 71 | 72 | We use [changesets](https://github.com/changesets/changesets) to handle any changes in the `changelog`. 73 | If a pull request created needs to bump a package version, please follow those steps to create a `changelog` 74 | 75 | 1. On the `root` folder, run `yarn changeset` and follow the prompt instructions (we follow [SemVer](https://semver.org/)) 76 | > Tips: Skip Major and Minor in prompt means a Patch update 77 | 2. Under `.changeset/` you will notice a new markdown file (its name is randomly generated), with the change-type and summary. 78 | 3. Push the file along with the rest of the changes 79 | 80 | Once your PR will be merged, our Github action will create a new PR with that generated changelog for us to merge, once the generated PR is merged a new version will be published to npm. 81 | -------------------------------------------------------------------------------- /packages/blocto-sdk/example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | Custom Provider 18 | 19 | 20 | 37 |
Enabling account ...
38 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED 2 | 3 |

4 | 5 | Blocto logo 6 | 7 |

8 | 9 | # Blocto JavaScript SDK 10 | 11 | > ⚠️ **Deprecation Notice** 12 | > 13 | > This repository is **no longer maintained** and has been officially deprecated. 14 | > 15 | > We recommend NOT using this SDK in new projects. 16 | > 17 | > For existing integrations, please be aware that no further updates, bug fixes, or support will be provided. 18 | > 19 | > **IMPORTANT**: As of June 11, 2025, all services associated with this SDK will be completely discontinued and existing integrations will cease to function. 20 | > 21 | > Thank you for your support and for being part of the Blocto developer community. 22 | 23 | This is a monorepo of Blocto JavaScript SDK. 24 | 25 | ## What's inside? 26 | 27 | This repo includes the following packages/apps: 28 | 29 | ### Apps and Packages 30 | 31 | - `packages`: shared packages 32 | - `adapters`: adapters using Blocto JavaScript SDK 33 | - `eslint-config-custom`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) 34 | - `tsconfig`: `tsconfig.json`s used throughout the monorepo 35 | 36 | ### Utilities 37 | 38 | This Turborepo has some additional tools already setup for you: 39 | 40 | - [TypeScript](https://www.typescriptlang.org/) for static type checking 41 | - [ESLint](https://eslint.org/) for code linting 42 | - [Prettier](https://prettier.io) for code formatting 43 | 44 | ## Repo structure 45 | 46 | ``` 47 | blocto-sdk 48 | ├─ packages 49 | │ ├─ @blocto/sdk 50 | │ │ └─ package.json 51 | │ ├─ tsconfig 52 | │ │ └─ package.json 53 | │ └─ eslint-config-custom 54 | │ └─ package.json 55 | ├─ adapters 56 | │ ├─ @blocto/aptos-wallet-adapter-plugin 57 | │ │ └─ package.json 58 | │ ├─ @blocto/rainbowkit-connector 59 | │ │ └─ package.json 60 | │ └─ @blocto/wagmi-connector 61 | │ │ └─ package.json 62 | │ ├─ @blocto/web3-react-connector 63 | │ │ └─ package.json 64 | └─ package.json 65 | ``` 66 | 67 | ## Build 68 | 69 | To build all apps and packages, run the following command: 70 | 71 | ``` 72 | yarn build 73 | ``` 74 | 75 | ## Contributing 76 | 77 | Feel like contributing? That's awesome! We have a 78 | [contributing guide](./CONTRIBUTING.md) to help guide you. 79 | 80 | ## Add changeset 81 | 82 | 1. Run the command line script `yarn changeset`. 83 | 2. Select the packages you want to include in the changeset using ↑ and ↓ to navigate to packages, and space to select a package. Hit enter when all desired packages are selected. 84 | 3. You will be prompted to select a bump type for each selected package. Select an appropriate bump type for the changes made. See [here](https://semver.org/) for information on semver versioning 85 | 4. Your final prompt will be to provide a message to go alongside the changeset. This will be written into the changelog when the next release occurs. 86 | After this, a new changeset will be added which is a markdown file with YAML front matter. 87 | 88 | ``` 89 | -| .changeset/ 90 | -|-| UNIQUE_ID.md 91 | ``` 92 | 93 | The message you typed can be found in the markdown file. If you want to expand on it, you can write as much markdown as you want, which will all be added to the changelog on publish. If you want to add more packages or change the bump types of any packages, that's also fine. 94 | 95 | While not every changeset is going to need a huge amount of detail, a good idea of what should be in a changeset is: 96 | 97 | - WHAT the change is 98 | - WHY the change was made 99 | - HOW a consumer should update their code 100 | 101 | 5. Once you are happy with the changeset, commit the file to your branch. 102 | 103 | ### Tips on adding changesets 104 | 105 | #### You can add more than one changeset to a pull request 106 | 107 | Changesets are designed to stack, so there's no problem with adding multiple. You might want to add more than one changeset when: 108 | 109 | - You want to release multiple packages with different changelog entries 110 | - You have made multiple changes to a package that should each be called out separately 111 | -------------------------------------------------------------------------------- /adapters/rainbowkit-connector/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import { bloctoWallet } from '../index'; 2 | 3 | describe('rainbowkit-connector', () => { 4 | 5 | const wallet = bloctoWallet(); 6 | 7 | test('defines name', () => { 8 | expect(typeof wallet.name).toBe('string'); 9 | }); 10 | 11 | test('defines id', () => { 12 | expect(typeof wallet.id).toBe('string'); 13 | }); 14 | 15 | test('defines icon', () => { 16 | expect(typeof wallet.iconUrl).toBe('string'); 17 | }); 18 | 19 | test('defines connect()', () => { 20 | expect(typeof wallet.createConnector).toBe('function'); 21 | }); 22 | 23 | const { connector } = wallet.createConnector({ 24 | rkDetails: { 25 | id: 'blocto', 26 | name: 'Blocto', 27 | shortName: 'Blocto', 28 | rdns: 'io.blocto', 29 | iconBackground: '#ffffff', 30 | iconUrl: 31 | 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjhweCIgaGVpZ2h0PSIyOHB4IiB2aWV3Qm94PSIwIDAgMjggMjgiIHZlcnNpb249IjEuMSI+CjxnIGlkPSJzdXJmYWNlMSI+CjxyZWN0IHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgZmlsbD0id2hpdGUiLz4KPHBhdGggc3R5bGU9IiBzdHJva2U6bm9uZTtmaWxsLXJ1bGU6bm9uemVybztmaWxsOnJnYig3Ljg0MzEzNyUsNjYuNjY2NjY3JSwxMDAlKTtmaWxsLW9wYWNpdHk6MTsiIGQ9Ik0gMTUuMzU1NDY5IDguNTQyOTY5IEMgMTMuMjUgOC41NDI5NjkgMTEuMTk1MzEyIDkuMzU1NDY5IDkuNjU2MjUgMTAuNzkyOTY5IEMgNy45NzI2NTYgMTIuMzc1IDYuOTA2MjUgMTQuNzA3MDMxIDYuMjk2ODc1IDE2LjkwMjM0NCBDIDUuODk0NTMxIDE4LjMzOTg0NCA1LjY5NTMxMiAxOS44MjgxMjUgNS42OTUzMTIgMjEuMzIwMzEyIEMgNS42OTUzMTIgMjEuNzY5NTMxIDUuNzEwOTM4IDIyLjIxODc1IDUuNzUgMjIuNjYwMTU2IEMgNS43OTI5NjkgMjMuMTk1MzEyIDYuMzE2NDA2IDIzLjU3MDMxMiA2LjgzNTkzOCAyMy40Mjk2ODggQyA3LjI4OTA2MiAyMy4zMDQ2ODggNy43Njk1MzEgMjMuMjM4MjgxIDguMjYxNzE5IDIzLjIzODI4MSBDIDkuMjczNDM4IDIzLjIzODI4MSAxMC4yMjI2NTYgMjMuNTE1NjI1IDExLjAzNTE1NiAyMy45OTYwOTQgQyAxMS4wNTQ2ODggMjQuMDA3ODEyIDExLjA3NDIxOSAyNC4wMTk1MzEgMTEuMDkzNzUgMjQuMDMxMjUgQyAxMi40MTc5NjkgMjQuODIwMzEyIDEzLjk3NjU2MiAyNS4yNTM5MDYgMTUuNjQwNjI1IDI1LjE5NTMxMiBDIDE5Ljk3NjU2MiAyNS4wNTQ2ODggMjMuNTE5NTMxIDIxLjUyMzQzOCAyMy42Nzk2ODggMTcuMTg3NSBDIDIzLjg1NTQ2OSAxMi40NDE0MDYgMjAuMDYyNSA4LjU0Mjk2OSAxNS4zNTU0NjkgOC41NDI5NjkgWiBNIDE1LjM1NTQ2OSAyMC42Nzk2ODggQyAxMy4yNTM5MDYgMjAuNjc5Njg4IDExLjU0Njg3NSAxOC45NzY1NjIgMTEuNTQ2ODc1IDE2Ljg3MTA5NCBDIDExLjU0Njg3NSAxNC43Njk1MzEgMTMuMjUzOTA2IDEzLjA2NjQwNiAxNS4zNTU0NjkgMTMuMDY2NDA2IEMgMTcuNDU3MDMxIDEzLjA2NjQwNiAxOS4xNjAxNTYgMTQuNzY5NTMxIDE5LjE2MDE1NiAxNi44NzEwOTQgQyAxOS4xNjAxNTYgMTguOTc2NTYyIDE3LjQ1NzAzMSAyMC42Nzk2ODggMTUuMzU1NDY5IDIwLjY3OTY4OCBaIE0gMTUuMzU1NDY5IDIwLjY3OTY4OCAiLz4KPHBhdGggc3R5bGU9IiBzdHJva2U6bm9uZTtmaWxsLXJ1bGU6bm9uemVybztmaWxsOnJnYigwJSw0NS44ODIzNTMlLDEwMCUpO2ZpbGwtb3BhY2l0eToxOyIgZD0iTSAxMS45Mjk2ODggNS45MTc5NjkgQyAxMS45Mjk2ODggNy4wMTU2MjUgMTEuMzU1NDY5IDguMDM1MTU2IDEwLjQxMDE1NiA4LjU5Mzc1IEMgOS44MTY0MDYgOC45NDUzMTIgOS4yNjE3MTkgOS4zNTkzNzUgOC43NTc4MTIgOS44MzIwMzEgQyA3LjY0MDYyNSAxMC44Nzg5MDYgNi44MDg1OTQgMTIuMTY0MDYyIDYuMTkxNDA2IDEzLjQzNzUgQyA2LjA3MDMxMiAxMy42ODc1IDUuNjkxNDA2IDEzLjU5NzY1NiA1LjY5MTQwNiAxMy4zMjAzMTIgTCA1LjY5MTQwNiA1LjkxNzk2OSBDIDUuNjkxNDA2IDQuMTk1MzEyIDcuMDg5ODQ0IDIuODAwNzgxIDguODEyNSAyLjgwMDc4MSBDIDEwLjUzNTE1NiAyLjgwMDc4MSAxMS45Mjk2ODggNC4xOTUzMTIgMTEuOTI5Njg4IDUuOTE3OTY5IFogTSAxMS45Mjk2ODggNS45MTc5NjkgIi8+CjwvZz4KPC9zdmc+Cg==', 32 | downloadUrls: { 33 | ios: 'https://apps.apple.com/app/blocto/id1481181682', 34 | android: 35 | 'https://play.google.com/store/apps/details?id=com.portto.blocto', 36 | }, 37 | installed: true, 38 | index: 4, 39 | groupIndex: 2, 40 | groupName: 'Other', 41 | isRainbowKitConnector: true, 42 | }, 43 | }); 44 | 45 | test('defines account()', () => { 46 | expect(typeof connector.connect).toBe('function'); 47 | }); 48 | 49 | test('defines disconnect()', () => { 50 | expect(typeof connector.disconnect).toBe('function'); 51 | }); 52 | 53 | test('defines getAccount()', () => { 54 | expect(typeof connector.getAccount).toBe('function'); 55 | }); 56 | 57 | test('defines getChainId()', () => { 58 | expect(typeof connector.getChainId).toBe('function'); 59 | }); 60 | 61 | test('defines getProvider()', () => { 62 | expect(typeof connector.getProvider).toBe('function'); 63 | }); 64 | 65 | test('defines switchChain()', () => { 66 | expect(typeof connector.switchChain).toBe('function'); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/providers/types/ethereum.d.ts: -------------------------------------------------------------------------------- 1 | import { IEthereumProvider } from 'eip1193-provider'; 2 | import { BaseConfig, KEY_SESSION } from '../../constants'; 3 | import BloctoProviderInterface from './blocto.d'; 4 | 5 | interface SingleChainConfig extends BaseConfig { 6 | chainId: string | number | null; 7 | rpc?: string; 8 | walletServer?: string; 9 | } 10 | 11 | interface MultiChainConfig extends BaseConfig { 12 | defaultChainId: string | number | null; 13 | walletServer?: string; 14 | switchableChains: AddEthereumChainParameter[]; 15 | } 16 | // EthereumProviderConfig can be both single chain or multi chain config. 17 | export type EthereumProviderConfig = SingleChainConfig | MultiChainConfig; 18 | 19 | export interface EIP1193RequestPayload { 20 | id?: number; 21 | jsonrpc?: string; 22 | method: string; 23 | params?: Array; 24 | callback?: JsonRpcCallback; 25 | } 26 | 27 | interface SwitchableNetwork { 28 | [id: number | string]: { 29 | name: string; 30 | display_name: string; 31 | network_type: string; 32 | wallet_web_url: string; 33 | rpc_url: string; 34 | }; 35 | } 36 | 37 | export interface EthereumProviderInterface 38 | extends BloctoProviderInterface, 39 | IEthereumProvider { 40 | chainId: string | number; 41 | networkVersion: string | number; 42 | rpc: string; 43 | _blocto: { 44 | sessionKeyEnv: KEY_SESSION; 45 | walletServer: string; 46 | blockchainName: string; 47 | networkType: string; 48 | switchableNetwork: SwitchableNetwork; 49 | }; 50 | sendUserOperation(userOp: IUserOperation): Promise; 51 | request( 52 | args: EIP1193RequestPayload | Array 53 | ): Promise; 54 | loadSwitchableNetwork( 55 | networkList: { 56 | chainId: string; 57 | rpcUrls?: string[]; 58 | }[] 59 | ): Promise; 60 | supportChainList(): Promise<{ chainId: string; chainName: string }[]>; 61 | injectedWalletServer?: string; 62 | } 63 | 64 | export interface AddEthereumChainParameter { 65 | chainId: string; 66 | rpcUrls: string[]; 67 | [key: string]: any; 68 | } 69 | 70 | export interface JsonRpcRequest { 71 | id?: string | undefined; 72 | jsonrpc: '2.0'; 73 | method: string; 74 | params?: Array; 75 | } 76 | 77 | export interface JsonRpcResponse { 78 | id: string | undefined; 79 | jsonrpc: '2.0'; 80 | method: string; 81 | result?: unknown; 82 | error?: Error; 83 | } 84 | 85 | export type JsonRpcCallback = ( 86 | error: Error | null, 87 | response?: JsonRpcResponse 88 | ) => unknown; 89 | 90 | export interface PromiseResponseItem { 91 | status: 'fulfilled' | 'rejected'; 92 | value?: any; 93 | reason?: any; 94 | } 95 | 96 | /** 97 | * A [[HexString]] whose length is even, which ensures it is a valid 98 | * representation of binary data. 99 | */ 100 | export type DataHexString = string; 101 | 102 | /** 103 | * An object that can be used to represent binary data. 104 | */ 105 | export type BytesLike = DataHexString | Uint8Array; 106 | 107 | /** 108 | * Any type that can be used where a numeric value is needed. 109 | */ 110 | export type Numeric = number | bigint; 111 | 112 | /** 113 | * Any type that can be used where a big number is needed. 114 | */ 115 | export type BigNumberish = string | Numeric; 116 | 117 | /** 118 | * An interface for an ERC-4337 transaction object. 119 | * Note: BloctoSDK do not need sender, nonce, initCode, signature to send userOperation. 120 | * These parameters will be ignored. 121 | */ 122 | export interface IUserOperation { 123 | callData: BytesLike; 124 | callGasLimit?: BigNumberish; 125 | verificationGasLimit?: BigNumberish; 126 | preVerificationGas?: BigNumberish; 127 | maxFeePerGas?: BigNumberish; 128 | maxPriorityFeePerGas?: BigNumberish; 129 | paymasterAndData?: BytesLike; 130 | /** 131 | * If provided, please ensure it is same as login account. 132 | */ 133 | sender?: string; 134 | /** 135 | * BloctoSDK do not need nonce to send userOperation. Will be ignored. 136 | * */ 137 | nonce?: BigNumberish; 138 | /** 139 | * BloctoSDK do not need initCode to send userOperation. Will be ignored. 140 | * */ 141 | initCode?: BytesLike; 142 | /** 143 | * BloctoSDK do not need signature to send userOperation. Will be ignored. 144 | * */ 145 | signature?: BytesLike; 146 | } 147 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/lib/storage/storage.ts: -------------------------------------------------------------------------------- 1 | import MemoryStorage, { isStorageSupported } from './memoryStorage'; 2 | import { 3 | LOGIN_PERSISTING_TIME, 4 | SDK_VERSION, 5 | KEY_SESSION, 6 | CHAIN, 7 | } from '../../constants'; 8 | 9 | export interface ProviderSession { 10 | code?: string | null; 11 | accounts: Partial>; 12 | evm: { 13 | [chainName: string]: string[] | undefined; 14 | }; 15 | } 16 | 17 | export interface AccountStorage { 18 | expiry: number; 19 | v: string; 20 | data: ProviderSession; 21 | } 22 | 23 | const storage = isStorageSupported() ? window.sessionStorage : MemoryStorage; 24 | 25 | export const getItem = ( 26 | key: string, 27 | defaultValue: T | null = null 28 | ): T | null => { 29 | const value = storage.getItem(key); 30 | try { 31 | return (value && JSON.parse(value)) || defaultValue; 32 | } catch (SyntaxError) { 33 | return (value as T) || defaultValue; 34 | } 35 | }; 36 | 37 | export const getRawItem = (key: string): string | null => storage.getItem(key); 38 | 39 | export const setItem = (key: string, value: unknown): void => 40 | storage.setItem( 41 | key, 42 | typeof value === 'string' ? value : JSON.stringify(value) 43 | ); 44 | 45 | export const removeItem = (key: string): void => { 46 | setItem(key, ''); // Due to some versions of browser bug can't removeItem correctly. 47 | storage.removeItem(key); 48 | }; 49 | 50 | /** 51 | * @param {KEY_SESSION} key - key to retrieve the data 52 | * @returns {ProviderSession | null} ProviderSession | null 53 | * @description 54 | * Get ProviderSession from storage. 55 | * If the data is expired, will remove the data and return null 56 | */ 57 | export const getAccountStorage = (key: KEY_SESSION): ProviderSession | null => { 58 | const rawAccountStorage = getItem(key, null); 59 | if (!rawAccountStorage) return null; 60 | 61 | // compare the expiry time of the item with the current time 62 | if ( 63 | new Date().getTime() > rawAccountStorage.expiry || 64 | rawAccountStorage.v !== SDK_VERSION 65 | ) { 66 | removeItem(key); 67 | return null; 68 | } 69 | 70 | return rawAccountStorage?.data; 71 | }; 72 | 73 | /** 74 | @param {KEY_SESSION} key - key to store the data 75 | @param {ProviderSession} data - Only the part of ProviderSession that needs to be updated 76 | @param {number} expiry - expiry time of the data 77 | */ 78 | export const setAccountStorage = ( 79 | key: KEY_SESSION, 80 | data: Partial, 81 | expiry?: number 82 | ): void => { 83 | const rawAccountStorage = getItem(key); 84 | const newAccountStorage: AccountStorage = { 85 | data: { 86 | code: data?.code || rawAccountStorage?.data?.code, 87 | accounts: { 88 | ...rawAccountStorage?.data?.accounts, 89 | ...data?.accounts, 90 | }, 91 | evm: { 92 | ...rawAccountStorage?.data?.evm, 93 | ...data?.evm, 94 | }, 95 | }, 96 | expiry: 97 | expiry || 98 | rawAccountStorage?.expiry || 99 | new Date().getTime() + LOGIN_PERSISTING_TIME, 100 | v: SDK_VERSION, 101 | }; 102 | setItem(key, newAccountStorage); 103 | return; 104 | }; 105 | 106 | export const getChainAddress = ( 107 | key: KEY_SESSION, 108 | chain: CHAIN 109 | ): string[] | null => { 110 | if (!getAccountStorage(key)?.code) { 111 | removeItem(key); 112 | return null; 113 | } 114 | return getAccountStorage(key)?.accounts?.[chain] || null; 115 | }; 116 | 117 | export const setChainAddress = ( 118 | key: KEY_SESSION, 119 | chain: CHAIN, 120 | account: string[] 121 | ): void => { 122 | setAccountStorage(key, { accounts: { [chain]: account } }); 123 | return; 124 | }; 125 | 126 | export const removeChainAddress = (key: KEY_SESSION, chain: string): void => { 127 | setAccountStorage(key, { accounts: { [chain]: undefined } }); 128 | return; 129 | }; 130 | 131 | export const getEvmAddress = ( 132 | key: KEY_SESSION, 133 | chain: string 134 | ): string[] | null => { 135 | if (!getAccountStorage(key)?.code) { 136 | removeItem(key); 137 | return null; 138 | } 139 | return getAccountStorage(key)?.evm?.[chain] || null; 140 | }; 141 | 142 | export const setEvmAddress = ( 143 | key: KEY_SESSION, 144 | chain: string, 145 | accounts: string[] 146 | ): void => { 147 | setAccountStorage(key, { evm: { [chain]: accounts } }); 148 | return; 149 | }; 150 | 151 | export const removeAllEvmAddress = (key: KEY_SESSION): void => { 152 | const newAccountStorage = getItem(key); 153 | if (!newAccountStorage) return; 154 | newAccountStorage.data.evm = {}; 155 | setItem(key, newAccountStorage); 156 | return; 157 | }; 158 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/constants.ts: -------------------------------------------------------------------------------- 1 | export enum KEY_SESSION { 2 | prod = 'BLOCTO_SDK', 3 | dev = 'BLOCTO_SDK_DEV', 4 | staging = 'BLOCTO_SDK_STAGING', 5 | } 6 | export enum CHAIN { 7 | ETHEREUM = 'ethereum', 8 | APTOS = 'aptos', 9 | } 10 | 11 | export interface BaseConfig { 12 | appId?: string; 13 | } 14 | 15 | type Mapping = Record; 16 | 17 | /* eth series constants begin */ 18 | 19 | export const ETH_RPC_LIST: Mapping = { 20 | // This is the list of public RPC endpoints that we known to be working 21 | // Used to help developers did not set up their own RPC endpoints 22 | 23 | // BSC mainnet 24 | 56: 'https://bsc-dataseed1.binance.org', 25 | // BSC testnet 26 | 97: 'https://data-seed-prebsc-1-s1.binance.org:8545', 27 | 28 | // Polygon Mainnet 29 | 137: 'https://polygon-rpc.com/', 30 | // Polygon Amoy Testnet 31 | 80002: 'https://rpc-amoy.polygon.technology/', 32 | 33 | // Avalanche Mainnet 34 | 43114: 'https://api.avax.network/ext/bc/C/rpc', 35 | // Avalanche Fuji Testnet 36 | 43113: 'https://api.avax-test.network/ext/bc/C/rpc', 37 | 38 | // Arbitrum Mainnet 39 | 42161: 'https://arb1.arbitrum.io/rpc', 40 | // Arbitrum Sepolia Testnet 41 | 421614: 'https://arbitrum-sepolia.blockpi.network/v1/rpc/public', 42 | 43 | // Optimism Mainnet 44 | 10: 'https://mainnet.optimism.io', 45 | // Optimism Sepolia Testnet 46 | 11155420: 'https://sepolia.optimism.io', 47 | 48 | // Base Mainnet 49 | 8453: 'https://mainnet.base.org', 50 | // Base Sepolia Testnet 51 | 84532: 'https://sepolia.base.org', 52 | 53 | // Zora 54 | 7777777: 'https://rpc.zora.energy', 55 | // Zora Sepolia Testnet 56 | 999999999: 'https://sepolia.rpc.zora.energy', 57 | 58 | // Scroll 59 | 534352: 'https://rpc.scroll.io', 60 | // Scroll Sepolia Testnet 61 | 534351: 'https://sepolia-rpc.scroll.io', 62 | 63 | // Linea 64 | 59144: 'https://rpc.linea.build', 65 | 66 | // zKatana Sepolia Testnet 67 | 1261120: 'https://rpc.startale.com/zkatana', 68 | 69 | // Blast 70 | 81457: 'https://rpc.blast.io', 71 | // Blast Sepolia Testnet 72 | 168587773: 'https://sepolia.blast.io', 73 | 74 | // Merlin Chain 75 | 4200: 'https://rpc.merlinchain.io', 76 | // Merlin Testnet 77 | 686868: 'https://testnet-rpc.merlinchain.io', 78 | 79 | // Story Testnet 80 | 1513: 'https://testnet.storyrpc.io', 81 | }; 82 | 83 | export const ETH_ENV_WALLET_SERVER_MAPPING: Mapping = { 84 | prod: 'https://wallet-v2.blocto.app', 85 | staging: 'https://wallet-v2-staging.blocto.app', 86 | dev: 'https://wallet-v2-dev.blocto.app', 87 | }; 88 | 89 | export const ETH_SESSION_KEY_MAPPING: Record = { 90 | prod: KEY_SESSION.prod, 91 | staging: KEY_SESSION.staging, 92 | dev: KEY_SESSION.dev, 93 | }; 94 | 95 | /* eth series constants end */ 96 | 97 | /* aptos constants begin */ 98 | 99 | export const APT_SESSION_KEY_MAPPING: Record = { 100 | 1: KEY_SESSION.prod, 101 | 2: KEY_SESSION.dev, 102 | 3: KEY_SESSION.dev, 103 | 4: KEY_SESSION.dev, 104 | 5: KEY_SESSION.staging, 105 | }; 106 | 107 | export const APT_CHAIN_ID_SERVER_MAPPING: Mapping = { 108 | // MAINNET 109 | 1: 'https://wallet-v2.blocto.app', 110 | // TESTNET 111 | 2: 'https://wallet-v2-dev.blocto.app', 112 | // DEVNET 113 | 3: 'https://wallet-v2-dev.blocto.app', 114 | // TESTING 115 | 4: 'https://wallet-v2-dev.blocto.app', 116 | // PREMAINNET 117 | 5: 'https://wallet-v2-staging.blocto.app', 118 | }; 119 | 120 | export enum WalletAdapterNetwork { 121 | Mainnet = 'mainnet', 122 | Testnet = 'testnet', 123 | Devnet = 'devnet', 124 | Testing = 'testing', 125 | Premainnet = 'premainnet', 126 | } 127 | 128 | export const APT_CHAIN_ID_NAME_MAPPING: Record = { 129 | 1: WalletAdapterNetwork.Mainnet, 130 | 2: WalletAdapterNetwork.Testnet, 131 | 3: WalletAdapterNetwork.Devnet, 132 | 4: WalletAdapterNetwork.Testing, 133 | 5: WalletAdapterNetwork.Premainnet, 134 | }; 135 | 136 | export const APT_CHAIN_ID_RPC_MAPPING: Mapping = { 137 | 1: 'https://fullnode.mainnet.aptoslabs.com/v1', 138 | 2: 'https://fullnode.testnet.aptoslabs.com/v1', 139 | 3: 'https://fullnode.devnet.aptoslabs.com/v1', 140 | 4: '', 141 | 5: 'https://premainnet.aptosdev.com/v1', 142 | }; 143 | 144 | /* aptos constants end */ 145 | 146 | export const EIP1193_EVENTS: Array = [ 147 | 'connect', 148 | 'disconnect', 149 | 'message', 150 | 'chainChanged', 151 | 'accountsChanged', 152 | ]; 153 | 154 | // Preserve login for 1 day 155 | export const LOGIN_PERSISTING_TIME = 86400 * 1000; 156 | export const DEFAULT_APP_ID = '00000000-0000-0000-0000-000000000000'; 157 | 158 | // Will inject the version of the SDK by rollup versionInjector during build time 159 | export const SDK_VERSION = '[VI]{version}[/VI]'; 160 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/__tests__/ethereum.test.ts: -------------------------------------------------------------------------------- 1 | import EthereumProvider from '../providers/ethereum'; 2 | import { getEvmSupport } from '../lib/getEvmSupport'; 3 | import { getEvmSupportList } from './fixtures/getEvmSupport'; 4 | jest.mock('../lib/getEvmSupport'); 5 | 6 | describe('Testing BloctoSDK ethereum provider initialization and network loading', () => { 7 | beforeEach(() => { 8 | (getEvmSupport as jest.Mock).mockResolvedValue(getEvmSupportList); 9 | }); 10 | 11 | test('should initialize with unloadedNetwork', () => { 12 | const ethereumWithSwitchable = new EthereumProvider({ 13 | defaultChainId: '0xaa36a7', 14 | switchableChains: [ 15 | { 16 | chainId: '0xaa36a7', 17 | rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'], 18 | }, 19 | { 20 | chainId: '0x61', 21 | rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], 22 | }, 23 | ], 24 | }); 25 | 26 | expect(ethereumWithSwitchable['_blocto'].unloadedNetwork).toBeDefined(); 27 | expect( 28 | ethereumWithSwitchable['_blocto']?.unloadedNetwork?.[0].chainId 29 | ).toBe('0xaa36a7'); 30 | expect( 31 | ethereumWithSwitchable['_blocto']?.unloadedNetwork?.[1].chainId 32 | ).toBe('0x61'); 33 | expect(ethereumWithSwitchable['_blocto'].unloadedNetwork?.length).toBe(2); 34 | }); 35 | 36 | test('get support chain list', async () => { 37 | const ethereum = new EthereumProvider({ 38 | chainId: '0xaa36a7', 39 | rpc: 'https://ethereum-sepolia.blockpi.network/v1/rpc/public', 40 | }); 41 | const supportedChains = await ethereum.supportChainList(); 42 | expect(supportedChains).toContainEqual({ 43 | chainId: '11155111', 44 | chainName: 'Sepolia', 45 | }); 46 | }); 47 | 48 | test('should add chain and switch to it', async () => { 49 | const ethereum = new EthereumProvider({ 50 | chainId: '0xaa36a7', 51 | rpc: 'https://ethereum-sepolia.blockpi.network/v1/rpc/public', 52 | }); 53 | await expect( 54 | ethereum.request({ 55 | method: 'wallet_switchEthereumChain', 56 | params: [{ chainId: '0x61' }], 57 | }) 58 | ).rejects.toThrow( 59 | 'Unrecognized chain ID "97". Try adding the chain using wallet_addEthereumChain first.' 60 | ); 61 | 62 | await ethereum.request({ 63 | method: 'wallet_addEthereumChain', 64 | params: [ 65 | { 66 | chainId: '0x61', 67 | rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], 68 | }, 69 | ], 70 | }); 71 | await ethereum.request({ 72 | method: 'wallet_switchEthereumChain', 73 | params: [{ chainId: '0x61' }], 74 | }); 75 | expect(ethereum.chainId).toBe('0x61'); 76 | }); 77 | 78 | test('create sdk instance with switchableChains and switch to it', async () => { 79 | const ethereum = new EthereumProvider({ 80 | defaultChainId: '0xaa36a7', 81 | switchableChains: [ 82 | { 83 | chainId: '0xaa36a7', 84 | rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'], 85 | }, 86 | { 87 | chainId: '0x61', 88 | rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], 89 | }, 90 | ], 91 | }); 92 | await ethereum.request({ 93 | method: 'wallet_switchEthereumChain', 94 | params: [{ chainId: '0x61' }], 95 | }); 96 | expect(ethereum.chainId).toBe('0x61'); 97 | }); 98 | test('create sdk instance with switchableChains and call eth_accounts', async () => { 99 | const ethereum = new EthereumProvider({ 100 | defaultChainId: '0xaa36a7', 101 | switchableChains: [ 102 | { 103 | chainId: '0xaa36a7', 104 | rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'], 105 | }, 106 | { 107 | chainId: '0x61', 108 | rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], 109 | }, 110 | ], 111 | }); 112 | // Trigger the loading of switchable networks 113 | await ethereum.request({ 114 | method: 'eth_accounts', 115 | }); 116 | expect(ethereum.chainId).toBe('0xaa36a7'); 117 | // should remove unloadedNetwork after loading 118 | expect(ethereum['_blocto'].unloadedNetwork).toBeUndefined(); 119 | }); 120 | 121 | test('should not call loadSwitchableNetwork if unloadedNetwork is empty', async () => { 122 | const ethereum = new EthereumProvider({ 123 | chainId: '0xaa36a7', 124 | rpc: 'https://ethereum-sepolia.blockpi.network/v1/rpc/public', 125 | }); 126 | const loadSwitchableNetworkSpy = jest.spyOn(ethereum, 'loadSwitchableNetwork'); 127 | 128 | await ethereum.request({ method: 'eth_accounts' }); 129 | 130 | expect(loadSwitchableNetworkSpy).not.toHaveBeenCalled(); 131 | }); 132 | }); 133 | -------------------------------------------------------------------------------- /adapters/web3modal-connector/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @blocto/web3modal-connector 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 267f154: fix(wagmi): correct typo with chainId 8 | - 48fa07a: fix: handle existedSDK handle window not defined 9 | - Updated dependencies [267f154] 10 | - Updated dependencies [48fa07a] 11 | - @blocto/wagmi-connector@1.3.1 12 | 13 | ## 0.1.4-beta.2 14 | 15 | ### Patch Changes 16 | 17 | - 267f154: fix(wagmi): correct typo with chainId 18 | - Updated dependencies [267f154] 19 | - @blocto/wagmi-connector@1.3.1-beta.2 20 | 21 | ## 0.1.4-beta.1 22 | 23 | ### Patch Changes 24 | 25 | - 48fa07a: fix: handle existedSDK handle window not defined 26 | - Updated dependencies [48fa07a] 27 | - @blocto/wagmi-connector@1.3.1-beta.1 28 | 29 | ## 0.1.4-beta.0 30 | 31 | ### Patch Changes 32 | 33 | - @blocto/wagmi-connector@1.3.1-beta.0 34 | 35 | ## 0.1.3 36 | 37 | ### Patch Changes 38 | 39 | - b9dac7d: support web3js v4 40 | - 8d0b5bf: enhance in-app-sdk event support 41 | - 00a3832: sendAsync can send another requests 42 | - Updated dependencies [b9dac7d] 43 | - Updated dependencies [8d0b5bf] 44 | - Updated dependencies [e075c22] 45 | - Updated dependencies [00a3832] 46 | - @blocto/wagmi-connector@1.3.0 47 | 48 | ## 0.1.3-beta.2 49 | 50 | ### Patch Changes 51 | 52 | - Updated dependencies [fce0e50] 53 | - @blocto/wagmi-connector@1.3.0-beta.2 54 | 55 | ## 0.1.3-beta.1 56 | 57 | ### Patch Changes 58 | 59 | - b9dac7d: support web3js v4 60 | - 00a3832: sendAsync can send another requests 61 | - Updated dependencies [b9dac7d] 62 | - Updated dependencies [00a3832] 63 | - @blocto/wagmi-connector@1.2.4-beta.1 64 | 65 | ## 0.1.3-beta.0 66 | 67 | ### Patch Changes 68 | 69 | - 8d0b5bf: enhance in-app-sdk event support 70 | - Updated dependencies [8d0b5bf] 71 | - @blocto/wagmi-connector@1.2.4-beta.0 72 | 73 | ## 0.1.2 74 | 75 | ### Patch Changes 76 | 77 | - 4835522: Fix export unreconize type for old typescript 78 | - Updated dependencies [4835522] 79 | - @blocto/wagmi-connector@1.2.2 80 | 81 | ## 0.1.2-beta.0 82 | 83 | ### Patch Changes 84 | 85 | - 4835522: Fix export unreconize type for old typescript 86 | - Updated dependencies [4835522] 87 | - @blocto/wagmi-connector@1.2.2-beta.0 88 | 89 | ## 0.1.1 90 | 91 | ### Patch Changes 92 | 93 | - 2515a8f: Fix wrongly disconnect chain when account not changed 94 | - b40fbed: Fix skip calling enable() when request wallet_disconnect method 95 | - 4c769f9: Clear error message when add not supported chain 96 | - bbf2160: Make loadSwitchableNetwork rpcUrls optional 97 | - a3b0243: Seperate evm accounts from other chains in storage data structure 98 | - Updated dependencies [2515a8f] 99 | - Updated dependencies [b40fbed] 100 | - Updated dependencies [4c769f9] 101 | - Updated dependencies [bbf2160] 102 | - Updated dependencies [a3b0243] 103 | - @blocto/wagmi-connector@1.2.1 104 | 105 | ## 0.1.1-beta.1 106 | 107 | ### Patch Changes 108 | 109 | - 2515a8f: Fix wrongly disconnect chain when account not changed 110 | - Updated dependencies [2515a8f] 111 | - @blocto/wagmi-connector@1.2.1-beta.1 112 | 113 | ## 0.1.1-beta.0 114 | 115 | ### Patch Changes 116 | 117 | - b40fbed: Fix skip calling enable() when request wallet_disconnect method 118 | - 4c769f9: Clear error message when add not supported chain 119 | - bbf2160: Make loadSwitchableNetwork rpcUrls optional 120 | - a3b0243: Seperate evm accounts from other chains in storage data structure 121 | - Updated dependencies [b40fbed] 122 | - Updated dependencies [4c769f9] 123 | - Updated dependencies [bbf2160] 124 | - Updated dependencies [a3b0243] 125 | - @blocto/wagmi-connector@1.2.1-beta.0 126 | 127 | ## 0.1.0 128 | 129 | ### Minor Changes 130 | 131 | - df576fe: - Adding Package `@blocto/web3modal-connector` to replace Package `@blocto/wagmi-connector`'s support for web3Modal 132 | - Removing `BloctoWeb3ModalConfig` exported by Package `@blocto/wagmi-connector` 133 | - Removing `BloctoOptions`'s deprecate params `chainId, rpc` from `@blocto/wagmi-connector` 134 | 135 | ### Patch Changes 136 | 137 | - Updated dependencies [21097d9] 138 | - Updated dependencies [83eb33d] 139 | - Updated dependencies [e0e8fb7] 140 | - Updated dependencies [55f3395] 141 | - Updated dependencies [3ceb547] 142 | - Updated dependencies [21097d9] 143 | - Updated dependencies [df576fe] 144 | - Updated dependencies [21097d9] 145 | - Updated dependencies [21097d9] 146 | - Updated dependencies [21097d9] 147 | - @blocto/wagmi-connector@1.2.0 148 | 149 | ## 0.1.0-beta.0 150 | 151 | ### Minor Changes 152 | 153 | - bc5cc4b: - Adding Package `@blocto/web3modal-connector` to replace Package `@blocto/wagmi-connector`'s support for web3Modal 154 | - Removing `BloctoWeb3ModalConfig` exported by Package `@blocto/wagmi-connector` 155 | - Removing `BloctoOptions`'s deprecate params `chainId, rpc` from `@blocto/wagmi-connector` 156 | 157 | ### Patch Changes 158 | 159 | - Updated dependencies [bc5cc4b] 160 | - @blocto/wagmi-connector@1.2.0-beta.8 161 | -------------------------------------------------------------------------------- /adapters/wagmi-connector/src/connector.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | EthereumProviderConfig as BloctoEthereumProviderParameters, 3 | EthereumProviderInterface as BloctoProvider, 4 | } from '@blocto/sdk'; 5 | import BloctoSDK from '@blocto/sdk'; 6 | import { createConnector, normalizeChainId } from '@wagmi/core'; 7 | import { 8 | RpcError, 9 | SwitchChainError, 10 | UserRejectedRequestError, 11 | getAddress, 12 | numberToHex, 13 | } from 'viem'; 14 | 15 | export type BloctoParameters = { 16 | /** 17 | * Your app’s unique identifier that can be obtained at https://developers.blocto.app, 18 | * To get advanced features and support with Blocto. 19 | * 20 | * https://docs.blocto.app/blocto-sdk/register-app-id 21 | */ 22 | appId?: string; 23 | }; 24 | 25 | blocto.type = 'blocto' as const; 26 | export function blocto({ appId }: BloctoParameters = {}) { 27 | // eslint-disable-next-line @typescript-eslint/ban-types 28 | type Properties = {}; 29 | type StorageItem = { 30 | store: any; 31 | 'wagmi.recentConnectorId': string; 32 | }; 33 | 34 | let walletProvider: BloctoProvider | undefined; 35 | const handleConnectReset = () => { 36 | walletProvider = undefined; 37 | }; 38 | 39 | return createConnector((config) => ({ 40 | id: 'blocto', 41 | name: 'Blocto', 42 | type: blocto.type, 43 | async connect({ chainId } = {}) { 44 | try { 45 | const provider = await this.getProvider({ chainId }); 46 | 47 | config.emitter.emit('message', { type: 'connecting' }); 48 | 49 | await provider.request({ 50 | method: 'eth_requestAccounts', 51 | }); 52 | 53 | const accounts = await this.getAccounts(); 54 | const _chainId = await this.getChainId(); 55 | 56 | return { accounts, chainId: _chainId }; 57 | } catch (error: unknown) { 58 | handleConnectReset(); 59 | throw error; 60 | } 61 | }, 62 | async disconnect() { 63 | const provider = await this.getProvider(); 64 | await provider.request({ method: 'wallet_disconnect' }); 65 | handleConnectReset(); 66 | }, 67 | async getAccounts() { 68 | const provider = await this.getProvider(); 69 | const accounts = (await provider.request({ 70 | method: 'eth_accounts', 71 | })) as string[]; 72 | 73 | return accounts.map((x) => getAddress(x)); 74 | }, 75 | async getChainId() { 76 | const provider = await this.getProvider(); 77 | const chainId = await provider?.request({ method: 'eth_chainId' }); 78 | return normalizeChainId(chainId); 79 | }, 80 | async getProvider({ chainId } = {}) { 81 | if (!walletProvider) { 82 | const store = await config.storage?.getItem('store'); 83 | const lastConnectedChainId = store?.state?.chainId; 84 | const desiredChainId = chainId ?? lastConnectedChainId; 85 | const ethereum: BloctoEthereumProviderParameters = { 86 | chainId: desiredChainId, 87 | rpc: config.chains.find((x) => x.id === desiredChainId)?.rpcUrls 88 | .default.http[0], 89 | }; 90 | 91 | walletProvider = new BloctoSDK({ ethereum, appId })?.ethereum; 92 | if (!walletProvider) { 93 | throw new Error('Blocto SDK is not initialized.'); 94 | } 95 | 96 | walletProvider.on('accountsChanged', this.onAccountsChanged.bind(this)); 97 | walletProvider.on('chainChanged', this.onChainChanged.bind(this)); 98 | walletProvider.on('disconnect', this.onDisconnect.bind(this)); 99 | } 100 | 101 | return Promise.resolve(walletProvider); 102 | }, 103 | async isAuthorized() { 104 | const recentConnectorId = await config.storage?.getItem( 105 | 'recentConnectorId' 106 | ); 107 | if (recentConnectorId !== this.id) return false; 108 | 109 | const accounts = await this.getAccounts(); 110 | return !!accounts.length; 111 | }, 112 | async switchChain({ chainId }) { 113 | try { 114 | const provider = await this.getProvider(); 115 | const id = numberToHex(chainId); 116 | const chain = config.chains.find((x) => x.id === chainId); 117 | const networks = await provider.supportChainList(); 118 | const evmSupportMap = networks.reduce( 119 | (a: any, v: any) => ({ ...a, [v.chainId]: v }), 120 | {} 121 | ); 122 | const isBloctoSupportChain = evmSupportMap[`${chainId}`]; 123 | 124 | if (!chain) { 125 | throw new SwitchChainError(new Error(`Chain not in config: ${id}`)); 126 | } 127 | 128 | if (!isBloctoSupportChain) { 129 | throw new SwitchChainError( 130 | new Error(`Blocto unsupported chain: ${id}`) 131 | ); 132 | } 133 | 134 | await provider.request({ 135 | method: 'wallet_addEthereumChain', 136 | params: [{ chainId: id, rpcUrls: chain?.rpcUrls.default.http }], 137 | }); 138 | await provider.request({ 139 | method: 'wallet_switchEthereumChain', 140 | params: [{ chainId: id }], 141 | }); 142 | 143 | return chain; 144 | } catch (err) { 145 | const error = err as RpcError; 146 | if (error.code === UserRejectedRequestError.code) 147 | throw new UserRejectedRequestError(error); 148 | 149 | throw new SwitchChainError(error as Error); 150 | } 151 | }, 152 | // eslint-disable-next-line @typescript-eslint/no-empty-function 153 | onAccountsChanged() {}, 154 | async onChainChanged(chainId: string) { 155 | const accounts = await this.getAccounts(); 156 | config.emitter.emit('change', { 157 | chainId: normalizeChainId(chainId), 158 | accounts, 159 | }); 160 | }, 161 | async onDisconnect() { 162 | config.emitter.emit('disconnect'); 163 | }, 164 | })); 165 | } 166 | 167 | export { createConnector }; -------------------------------------------------------------------------------- /adapters/aptos-wallet-adapter-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { AptosProviderInterface as IBloctoAptos } from '@blocto/sdk'; 2 | import BloctoSDK from '@blocto/sdk'; 3 | import type { 4 | AccountInfo, 5 | AdapterPlugin, 6 | NetworkInfo, 7 | SignMessagePayload, 8 | SignMessageResponse, 9 | WalletName, 10 | } from '@aptos-labs/wallet-adapter-core'; 11 | import { NetworkName, WalletReadyState } from '@aptos-labs/wallet-adapter-core'; 12 | import type { Types } from 'aptos'; 13 | 14 | interface BloctoWindow extends Window { 15 | bloctoAptos?: IBloctoAptos; 16 | } 17 | 18 | declare const window: BloctoWindow; 19 | 20 | export const BloctoWalletName = 'Blocto' as WalletName<'Blocto'>; 21 | 22 | export interface BloctoWalletAdapterConfig { 23 | network?: NetworkName.Mainnet | NetworkName.Testnet; 24 | bloctoAppId: string; 25 | } 26 | 27 | export const APTOS_NETWORK_CHAIN_ID_MAPPING = { 28 | // MAINNET 29 | [NetworkName.Mainnet]: 1, 30 | // TESTNET 31 | [NetworkName.Testnet]: 2, 32 | }; 33 | 34 | export class BloctoWallet implements AdapterPlugin { 35 | readonly name = BloctoWalletName; 36 | readonly url = 'https://blocto.app'; 37 | readonly icon = 38 | 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTI2LjkwMjggMTIuMzAyNEMyMi4zOTEyIDEyLjMwMjQgMTcuOTg3NCAxNC4wNDIgMTQuNjk1MiAxNy4xMjhDMTEuMDg0NCAyMC41MTM3IDguNzk5MiAyNS41MTM4IDcuNDg5MzIgMzAuMjE3M0M2LjYzMTQgMzMuMjk1MyA2LjIwMTY0IDM2LjQ4NzYgNi4yMDE2NCAzOS42ODE0QzYuMjAxNjQgNDAuNjQ3MiA2LjI0MTI5IDQxLjYwNSA2LjMxNzQxIDQyLjU1MTdDNi40MTA5NyA0My43MDMgNy41MzIxNCA0NC41MDA3IDguNjQ4NTUgNDQuMTk5NEM5LjYyMjI0IDQzLjkzNzcgMTAuNjQ2NyA0My43OTY2IDExLjcwMjggNDMuNzk2NkMxMy44NzIyIDQzLjc5NjYgMTUuOTA1MiA0NC4zODY1IDE3LjY0OCA0NS40MTczQzE3LjY5MDggNDUuNDQyNiAxNy43MzIxIDQ1LjQ2OCAxNy43NzQ5IDQ1LjQ5MThDMjAuNjA3MiA0Ny4xODA3IDIzLjk0ODUgNDguMTA4NCAyNy41MTE4IDQ3Ljk4OTVDMzYuODA2MiA0Ny42ODE4IDQ0LjM5OTEgNDAuMTE5MSA0NC43NDE2IDMwLjgyNjJDNDUuMTE1OSAyMC42NTk2IDM2Ljk4NyAxMi4zMDA4IDI2LjkwNDQgMTIuMzAwOEwyNi45MDI4IDEyLjMwMjRaTTI2LjkwMjggMzguMzA4MUMyMi4zOTc1IDM4LjMwODEgMTguNzQ1NCAzNC42NTYgMTguNzQ1NCAzMC4xNTIzQzE4Ljc0NTQgMjUuNjQ4NiAyMi4zOTc1IDIxLjk5NDggMjYuOTAyOCAyMS45OTQ4QzMxLjQwODEgMjEuOTk0OCAzNS4wNjAyIDI1LjY0NyAzNS4wNjAyIDMwLjE1MjNDMzUuMDYwMiAzNC42NTc1IDMxLjQwODEgMzguMzA4MSAyNi45MDI4IDM4LjMwODFaIiBmaWxsPSIjMTRBQUZGIi8+CjxwYXRoIGQ9Ik0xOS41NjM3IDYuNjgyNjFDMTkuNTYzNyA5LjAzNDM2IDE4LjMzMTUgMTEuMjE2NCAxNi4zMDggMTIuNDE1M0MxNS4wMzc4IDEzLjE2ODYgMTMuODQ2OCAxNC4wNTgyIDEyLjc2ODUgMTUuMDcxNUMxMC4zNzU1IDE3LjMxMzkgOC41ODk4NSAyMC4wNjUzIDcuMjY3MjggMjIuNzkyOUM3LjAwNzIxIDIzLjMzMDQgNi4yMDAwMyAyMy4xNDAyIDYuMjAwMDMgMjIuNTQyM1Y2LjY4MjYxQzYuMjAwMDMgMi45OTI0MiA5LjE5MjQ1IDAgMTIuODgyNiAwQzE2LjU3MjggMCAxOS41NjUyIDIuOTkyNDIgMTkuNTY1MiA2LjY4MjYxSDE5LjU2MzdaIiBmaWxsPSIjMDA3NUZGIi8+Cjwvc3ZnPgo='; 39 | 40 | readonly providerName = 'bloctoAptos'; 41 | 42 | provider: IBloctoAptos | undefined = 43 | typeof window !== 'undefined' ? window.bloctoAptos : undefined; 44 | 45 | readyState?: WalletReadyState = WalletReadyState.Loadable; 46 | 47 | protected _network: NetworkName.Mainnet | NetworkName.Testnet; 48 | 49 | constructor({ 50 | network = NetworkName.Mainnet, 51 | bloctoAppId, 52 | }: BloctoWalletAdapterConfig) { 53 | const sdk = new BloctoSDK({ 54 | aptos: { 55 | chainId: APTOS_NETWORK_CHAIN_ID_MAPPING[network], 56 | }, 57 | appId: bloctoAppId, 58 | }); 59 | 60 | this.provider = sdk.aptos; 61 | this._network = network; 62 | } 63 | 64 | async connect(): Promise { 65 | const accountInfo = await this.provider?.connect(); 66 | if (!accountInfo) throw `${BloctoWalletName} Address Info Error`; 67 | if (!accountInfo.address) throw `${BloctoWalletName} address null`; 68 | if (!accountInfo.publicKey) throw `${BloctoWalletName} publicKey null`; 69 | if (!accountInfo.minKeysRequired) 70 | throw `${BloctoWalletName} minKeysRequired null`; 71 | return { 72 | address: accountInfo.address, 73 | publicKey: accountInfo.publicKey, 74 | minKeysRequired: accountInfo.minKeysRequired, 75 | }; 76 | } 77 | 78 | async account(): Promise { 79 | const response = await this.provider?.publicAccount; 80 | if (!response) throw `${BloctoWalletName} Account Error`; 81 | if (!response.address) throw `${BloctoWalletName} address null`; 82 | if (!response.publicKey) throw `${BloctoWalletName} publicKey null`; 83 | if (!response.minKeysRequired) 84 | throw `${BloctoWalletName} minKeysRequired null`; 85 | return { 86 | address: response.address, 87 | publicKey: response.publicKey, 88 | minKeysRequired: response.minKeysRequired, 89 | }; 90 | } 91 | 92 | async disconnect(): Promise { 93 | await this.provider?.disconnect(); 94 | } 95 | 96 | async signAndSubmitTransaction( 97 | transaction: Types.TransactionPayload, 98 | options?: any 99 | ): Promise<{ hash: Types.HexEncodedBytes }> { 100 | const provider = this.provider; 101 | const response = await provider?.signAndSubmitTransaction( 102 | transaction, 103 | options 104 | ); 105 | if (response) { 106 | return { hash: response.hash }; 107 | } else { 108 | throw new Error('Transaction failed'); 109 | } 110 | } 111 | 112 | async signMessage(message: SignMessagePayload): Promise { 113 | if (typeof message !== 'object' || !message.nonce) { 114 | `${BloctoWalletName} Invalid signMessage Payload`; 115 | } 116 | const response = await this.provider?.signMessage(message); 117 | if (response) { 118 | return response; 119 | } else { 120 | throw `${BloctoWalletName} Sign Message failed`; 121 | } 122 | } 123 | 124 | async network(): Promise { 125 | const response = await this.provider?.network(); 126 | if (!response) throw `${BloctoWalletName} Network Error`; 127 | const name = response.name as unknown; 128 | return { 129 | name: name as NetworkName, 130 | chainId: response.chainId, 131 | }; 132 | } 133 | 134 | async onNetworkChange(): Promise { 135 | // not supported yet 136 | return Promise.resolve(); 137 | } 138 | 139 | async onAccountChange(): Promise { 140 | // not supported yet 141 | return Promise.resolve(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /packages/blocto-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "ES6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */, 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ 10 | "declaration": true, 11 | "declarationDir": "./dist/types" /* Generates corresponding '.d.ts' file. */, 12 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | // "outDir": "./", /* Redirect output structure to the directory. */ 16 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 41 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */ 42 | // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ 43 | 44 | /* Module Resolution Options */ 45 | "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, 46 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 47 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 48 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 49 | // "typeRoots": [], /* List of folders to include type definitions from. */ 50 | // "types": [], /* Type declaration files to be included in compilation. */ 51 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 52 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 53 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 54 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 55 | 56 | /* Source Map Options */ 57 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 58 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 59 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 60 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 61 | 62 | /* Experimental Options */ 63 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 64 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 65 | 66 | /* Advanced Options */ 67 | "skipLibCheck": true /* Skip type checking of declaration files. */, 68 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 69 | }, 70 | "include": ["./src/**/*.ts"] 71 | } 72 | -------------------------------------------------------------------------------- /adapters/connectkit-connector/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @blocto/connectkit-connector 2 | 3 | ## 0.2.3 4 | 5 | ### Patch Changes 6 | 7 | - 267f154: fix(wagmi): correct typo with chainId 8 | - 48fa07a: fix: handle existedSDK handle window not defined 9 | - Updated dependencies [267f154] 10 | - Updated dependencies [48fa07a] 11 | - @blocto/wagmi-connector@1.3.1 12 | 13 | ## 0.2.3-beta.2 14 | 15 | ### Patch Changes 16 | 17 | - 267f154: fix(wagmi): correct typo with chainId 18 | - Updated dependencies [267f154] 19 | - @blocto/wagmi-connector@1.3.1-beta.2 20 | 21 | ## 0.2.3-beta.1 22 | 23 | ### Patch Changes 24 | 25 | - 48fa07a: fix: handle existedSDK handle window not defined 26 | - Updated dependencies [48fa07a] 27 | - @blocto/wagmi-connector@1.3.1-beta.1 28 | 29 | ## 0.2.3-beta.0 30 | 31 | ### Patch Changes 32 | 33 | - @blocto/wagmi-connector@1.3.1-beta.0 34 | 35 | ## 0.2.2 36 | 37 | ### Patch Changes 38 | 39 | - b9dac7d: support web3js v4 40 | - 8d0b5bf: enhance in-app-sdk event support 41 | - 00a3832: sendAsync can send another requests 42 | - Updated dependencies [b9dac7d] 43 | - Updated dependencies [8d0b5bf] 44 | - Updated dependencies [e075c22] 45 | - Updated dependencies [00a3832] 46 | - @blocto/wagmi-connector@1.3.0 47 | 48 | ## 0.2.2-beta.2 49 | 50 | ### Patch Changes 51 | 52 | - Updated dependencies [fce0e50] 53 | - @blocto/wagmi-connector@1.3.0-beta.2 54 | 55 | ## 0.2.2-beta.1 56 | 57 | ### Patch Changes 58 | 59 | - b9dac7d: support web3js v4 60 | - 00a3832: sendAsync can send another requests 61 | - Updated dependencies [b9dac7d] 62 | - Updated dependencies [00a3832] 63 | - @blocto/wagmi-connector@1.2.4-beta.1 64 | 65 | ## 0.2.2-beta.0 66 | 67 | ### Patch Changes 68 | 69 | - 8d0b5bf: enhance in-app-sdk event support 70 | - Updated dependencies [8d0b5bf] 71 | - @blocto/wagmi-connector@1.2.4-beta.0 72 | 73 | ## 0.2.1 74 | 75 | ### Patch Changes 76 | 77 | - 4835522: Fix export unreconize type for old typescript 78 | - Updated dependencies [4835522] 79 | - @blocto/wagmi-connector@1.2.2 80 | 81 | ## 0.2.1-beta.0 82 | 83 | ### Patch Changes 84 | 85 | - 4835522: Fix export unreconize type for old typescript 86 | - Updated dependencies [4835522] 87 | - @blocto/wagmi-connector@1.2.2-beta.0 88 | 89 | ## 0.2.0 90 | 91 | ### Minor Changes 92 | 93 | - 464a645: enhance the connecting experience with connectkit using @blocto/connectkit-connector 94 | 95 | ### Patch Changes 96 | 97 | - 2515a8f: Fix wrongly disconnect chain when account not changed 98 | - b40fbed: Fix skip calling enable() when request wallet_disconnect method 99 | - 4c769f9: Clear error message when add not supported chain 100 | - bbf2160: Make loadSwitchableNetwork rpcUrls optional 101 | - a3b0243: Seperate evm accounts from other chains in storage data structure 102 | - Updated dependencies [2515a8f] 103 | - Updated dependencies [b40fbed] 104 | - Updated dependencies [4c769f9] 105 | - Updated dependencies [bbf2160] 106 | - Updated dependencies [a3b0243] 107 | - @blocto/wagmi-connector@1.2.1 108 | 109 | ## 0.1.2-beta.1 110 | 111 | ### Patch Changes 112 | 113 | - 2515a8f: Fix wrongly disconnect chain when account not changed 114 | - Updated dependencies [2515a8f] 115 | - @blocto/sdk@0.7.0-beta.1 116 | 117 | ## 0.1.2-beta.0 118 | 119 | ### Patch Changes 120 | 121 | - b40fbed: Fix skip calling enable() when request wallet_disconnect method 122 | - 4c769f9: Clear error message when add not supported chain 123 | - bbf2160: Make loadSwitchableNetwork rpcUrls optional 124 | - a3b0243: Seperate evm accounts from other chains in storage data structure 125 | - Updated dependencies [b40fbed] 126 | - Updated dependencies [4c769f9] 127 | - Updated dependencies [bbf2160] 128 | - Updated dependencies [a3b0243] 129 | - Updated dependencies [1288bd1] 130 | - @blocto/sdk@0.7.0-beta.0 131 | 132 | ## 0.1.1 133 | 134 | ### Patch Changes 135 | 136 | - 21097d9: Fix switch chain is connected logic 137 | - 55f3395: Fix go login flow when switching to a different blocto server 138 | - 3ceb547: Fix skip switch chain if provide same id as current 139 | - 21097d9: Fix disconnect all evm chains when disconnect 140 | - 21097d9: Fix wrong switch chain url 141 | - 21097d9: Fix switch chain login logic 142 | - 21097d9: Fix emit disconnect event when switch chain approved but failed 143 | - Updated dependencies [21097d9] 144 | - Updated dependencies [e0e8fb7] 145 | - Updated dependencies [6e427b1] 146 | - Updated dependencies [34a23e4] 147 | - Updated dependencies [55f3395] 148 | - Updated dependencies [3ceb547] 149 | - Updated dependencies [21097d9] 150 | - Updated dependencies [21097d9] 151 | - Updated dependencies [21097d9] 152 | - Updated dependencies [21097d9] 153 | - Updated dependencies [494ded1] 154 | - @blocto/sdk@0.6.0 155 | 156 | ## 0.1.1-beta.7 157 | 158 | ### Patch Changes 159 | 160 | - 55f3395: Fix go login flow when switching to a different blocto server 161 | - Updated dependencies [6e427b1] 162 | - Updated dependencies [55f3395] 163 | - Updated dependencies [494ded1] 164 | - @blocto/sdk@0.6.0-beta.7 165 | 166 | ## 0.1.1-beta.6 167 | 168 | ### Patch Changes 169 | 170 | - 3ceb547: Fix skip switch chain if provide same id as current 171 | - Updated dependencies [34a23e4] 172 | - Updated dependencies [3ceb547] 173 | - @blocto/sdk@0.6.0-beta.6 174 | 175 | ## 0.1.1-beta.5 176 | 177 | ### Patch Changes 178 | 179 | - 39754e5: Fix disconnect all evm chains when disconnect 180 | - Updated dependencies [39754e5] 181 | - @blocto/sdk@0.6.0-beta.5 182 | 183 | ## 0.1.1-beta.4 184 | 185 | ### Patch Changes 186 | 187 | - 6acf18d: Fix switch chain is connected logic 188 | - Updated dependencies [6acf18d] 189 | - @blocto/sdk@0.6.0-beta.4 190 | 191 | ## 0.1.1-beta.3 192 | 193 | ### Patch Changes 194 | 195 | - 84d6727: Fix emit disconnect event when switch chain approved but failed 196 | - Updated dependencies [84d6727] 197 | - @blocto/sdk@0.6.0-beta.3 198 | 199 | ## 0.1.1-beta.2 200 | 201 | ### Patch Changes 202 | 203 | - a0cc54c: Fix switch chain login logic 204 | - Updated dependencies [a0cc54c] 205 | - @blocto/sdk@0.6.0-beta.2 206 | 207 | ## 0.1.1-beta.1 208 | 209 | ### Patch Changes 210 | 211 | - 0d5bfd5: Fix wrong switch chain url 212 | - Updated dependencies [0d5bfd5] 213 | - @blocto/sdk@0.6.0-beta.1 214 | 215 | ## 0.1.1-beta.0 216 | 217 | ### Patch Changes 218 | 219 | - Updated dependencies [e0e8fb7] 220 | - @blocto/sdk@0.6.0-beta.0 221 | 222 | ## 0.1.0 223 | 224 | ### Minor Changes 225 | 226 | - 9b82b57: add connectkit support 227 | 228 | ### Patch Changes 229 | 230 | - ac63830: wagmi three-shake config and rainbowkit use wagmi-connector 231 | - Updated dependencies [abd96b2] 232 | - Updated dependencies [fec7693] 233 | - Updated dependencies [dca87b8] 234 | - Updated dependencies [b9f1eca] 235 | - Updated dependencies [2cacc63] 236 | - @blocto/sdk@0.5.5 237 | -------------------------------------------------------------------------------- /adapters/wagmi-connector/src/connector.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test, describe, vi, beforeEach, afterEach } from 'vitest'; 2 | import { createConfig } from '@wagmi/core'; 3 | import { polygonMumbai, arbitrumGoerli } from '@wagmi/chains'; 4 | import { SwitchChainError, http, numberToHex } from 'viem'; 5 | import { normalizeChainId } from '@wagmi/core'; 6 | import { blocto } from './'; 7 | 8 | const walletProvider = { 9 | on: vi.fn(), 10 | }; 11 | 12 | describe('blocto-connector', () => { 13 | let connector: any; 14 | beforeEach(() => { 15 | const config = createConfig({ 16 | chains: [polygonMumbai, arbitrumGoerli], 17 | pollingInterval: 100, 18 | storage: null, 19 | transports: { 20 | [polygonMumbai.id]: http(), 21 | [arbitrumGoerli.id]: http(), 22 | }, 23 | }); 24 | connector = config._internal.connectors.setup(blocto()); 25 | }); 26 | 27 | afterEach(() => { 28 | connector = null; 29 | }); 30 | 31 | test('setup', () => { 32 | expect(connector.name).toEqual('Blocto'); 33 | }); 34 | 35 | test('connect', async () => { 36 | const chainId = 1; 37 | const accounts = ['0xc61B4Aa62E5FD40cceB08C602Eb5D157b257b49a']; 38 | const provider = { 39 | request: vi.fn().mockResolvedValue(accounts), 40 | }; 41 | connector.getProvider = vi.fn().mockResolvedValue(provider); 42 | connector.getAccounts = vi.fn().mockResolvedValue(accounts); 43 | connector.getChainId = vi.fn().mockResolvedValue(chainId); 44 | 45 | const result = await connector.connect({ chainId }); 46 | 47 | expect(result).toEqual({ accounts, chainId }); 48 | expect(connector.getProvider).toHaveBeenCalledWith({ chainId }); 49 | expect(provider.request).toHaveBeenCalledWith({ 50 | method: 'eth_requestAccounts', 51 | }); 52 | }); 53 | 54 | test('catch error when user decline to connect', () => { 55 | const chainId = 1; 56 | const userRejectedRequest = new Error('User rejected request'); 57 | const provider = { 58 | request: vi.fn().mockImplementation(() => { 59 | throw userRejectedRequest; 60 | }), 61 | }; 62 | connector.getProvider = vi.fn().mockResolvedValue(provider); 63 | 64 | expect(connector.connect({ chainId })).rejects.toThrow(userRejectedRequest); 65 | }); 66 | 67 | test('disconnect', async () => { 68 | const provider = { 69 | request: vi.fn().mockResolvedValue(undefined), 70 | }; 71 | connector.getProvider = vi.fn().mockResolvedValue(provider); 72 | 73 | await connector.disconnect(); 74 | 75 | expect(connector.getProvider).toHaveBeenCalled(); 76 | expect(provider.request).toHaveBeenCalledWith({ 77 | method: 'wallet_disconnect', 78 | }); 79 | }); 80 | 81 | test('getAccounts', async () => { 82 | const accounts = ['0xc61B4Aa62E5FD40cceB08C602Eb5D157b257b49a']; 83 | const provider = { 84 | request: vi.fn().mockResolvedValue(accounts), 85 | }; 86 | connector.getProvider = vi.fn().mockResolvedValue(provider); 87 | 88 | const result = await connector.getAccounts(); 89 | 90 | expect(result).toEqual(['0xc61B4Aa62E5FD40cceB08C602Eb5D157b257b49a']); 91 | expect(connector.getProvider).toHaveBeenCalled(); 92 | expect(provider.request).toHaveBeenCalledWith({ method: 'eth_accounts' }); 93 | }); 94 | 95 | test('getChainId', async () => { 96 | const chainId = '0x1'; 97 | const provider = { 98 | chainId: undefined, 99 | request: vi.fn().mockResolvedValue(chainId), 100 | }; 101 | connector.getProvider = vi.fn().mockResolvedValue(provider); 102 | 103 | const result = await connector.getChainId(); 104 | 105 | expect(result).toEqual(normalizeChainId(chainId)); 106 | expect(connector.getProvider).toHaveBeenCalled(); 107 | expect(provider.request).toHaveBeenCalledWith({ method: 'eth_chainId' }); 108 | }); 109 | 110 | test('getProvider', async () => { 111 | vi.mock('@blocto/sdk', () => ({ 112 | default: vi.fn().mockImplementation(() => ({ 113 | ethereum: walletProvider, 114 | })), 115 | })); 116 | 117 | const chainId = 1; 118 | const result = await connector.getProvider({ chainId }); 119 | 120 | expect(result).toEqual(walletProvider); 121 | expect(walletProvider.on).toHaveBeenCalledWith( 122 | 'accountsChanged', 123 | expect.any(Function) 124 | ); 125 | expect(walletProvider.on).toHaveBeenCalledWith( 126 | 'chainChanged', 127 | expect.any(Function) 128 | ); 129 | expect(walletProvider.on).toHaveBeenCalledWith( 130 | 'disconnect', 131 | expect.any(Function) 132 | ); 133 | }); 134 | test('isAuthorized', async () => { 135 | const accounts = ['0xc61B4Aa62E5FD40cceB08C602Eb5D157b257b49a']; 136 | connector.getAccounts = vi.fn().mockResolvedValue(accounts); 137 | 138 | const result = await connector.isAuthorized(); 139 | 140 | expect(result).toEqual(false); 141 | }); 142 | 143 | test('switchChain', async () => { 144 | const chainId = arbitrumGoerli.id; 145 | const provider = { 146 | request: vi.fn().mockResolvedValue(undefined), 147 | supportChainList: vi.fn().mockResolvedValue( 148 | [polygonMumbai, arbitrumGoerli].map(({ id, name }) => ({ 149 | chainId: id, 150 | chainName: name, 151 | })) 152 | ), 153 | }; 154 | connector.getProvider = vi.fn().mockResolvedValue(provider); 155 | 156 | const chain = await connector.switchChain({ chainId }); 157 | 158 | expect(connector.getProvider).toHaveBeenCalled(); 159 | expect(provider.request).toHaveBeenCalledWith({ 160 | method: 'wallet_addEthereumChain', 161 | params: [ 162 | { 163 | chainId: numberToHex(chainId), 164 | rpcUrls: arbitrumGoerli.rpcUrls.default.http, 165 | }, 166 | ], 167 | }); 168 | expect(provider.request).toHaveBeenCalledWith({ 169 | method: 'wallet_switchEthereumChain', 170 | params: [{ chainId: numberToHex(chainId) }], 171 | }); 172 | expect(chain.id).toEqual(chainId); 173 | }); 174 | 175 | test('catch error when switching to unConfigured chain', async () => { 176 | const unConfiguredChainId = 111111; 177 | const provider = { 178 | request: vi.fn().mockResolvedValue(undefined), 179 | supportChainList: vi.fn().mockResolvedValue( 180 | [polygonMumbai, arbitrumGoerli].map(({ id, name }) => ({ 181 | chainId: id, 182 | chainName: name, 183 | })) 184 | ), 185 | }; 186 | connector.getProvider = vi.fn().mockResolvedValue(provider); 187 | const expectError = new SwitchChainError( 188 | new Error(`Chain not in config: ${numberToHex(unConfiguredChainId)}`) 189 | ); 190 | 191 | expect( 192 | connector.switchChain({ chainId: unConfiguredChainId }) 193 | ).rejects.toThrow(expectError); 194 | }); 195 | 196 | test('catch error when switching to blocto unsupported chain', async () => { 197 | const unsupportedChainId = arbitrumGoerli.id; 198 | const provider = { 199 | request: vi.fn().mockResolvedValue(undefined), 200 | supportChainList: vi.fn().mockResolvedValue( 201 | [polygonMumbai].map(({ id, name }) => ({ 202 | chainId: id, 203 | chainName: name, 204 | })) 205 | ), 206 | }; 207 | connector.getProvider = vi.fn().mockResolvedValue(provider); 208 | const expectError = new SwitchChainError( 209 | new Error(`Blocto unsupported chain: ${numberToHex(unsupportedChainId)}`) 210 | ); 211 | 212 | expect( 213 | connector.switchChain({ chainId: unsupportedChainId }) 214 | ).rejects.toThrow(expectError); 215 | }); 216 | }); 217 | -------------------------------------------------------------------------------- /packages/dappauth/test/unit/index.test.js: -------------------------------------------------------------------------------- 1 | import { privateToPublic, stripHexPrefix } from 'ethereumjs-util'; 2 | import { equal } from 'assert'; 3 | import DappAuth from '../../src/index.js'; 4 | import { removeHexPrefix } from '../../src/utils/index.js'; 5 | import ProviderMock from './provider-mock.js'; 6 | import ContractMock from './contract-mock.js'; 7 | import { generateRandomKey, keyToAddress, signEOAPersonalMessage, signERC1654PersonalMessage } from './test-utils.js'; 8 | 9 | describe('DappAuth', function() { 10 | const keyA = generateRandomKey(); 11 | const keyB = generateRandomKey(); 12 | const keyC = generateRandomKey(); 13 | 14 | const testCases = [ 15 | { 16 | title: 'External wallets should be authorized signers over their address', 17 | isEOA: true, 18 | challenge: 'foo', 19 | challengeSign: 'foo', 20 | signingKeys: [keyA], 21 | authAddr: keyToAddress(keyA), 22 | mockContract: { 23 | authorizedKey: null, 24 | address: null, 25 | errorIsValidSignature: false, 26 | }, 27 | expectedAuthorizedSignerError: false, 28 | expectedAuthorizedSigner: true, 29 | }, 30 | { 31 | title: 32 | 'External wallets should NOT be authorized signers when signing the wrong challenge', 33 | isEOA: true, 34 | challenge: 'foo', 35 | challengeSign: 'bar', 36 | signingKeys: [keyA], 37 | authAddr: keyToAddress(keyA), 38 | mockContract: { 39 | authorizedKey: privateToPublic(keyC), 40 | address: keyToAddress(keyA), 41 | errorIsValidSignature: false, 42 | }, 43 | expectedAuthorizedSignerError: false, 44 | expectedAuthorizedSigner: false, 45 | }, 46 | { 47 | title: 48 | 'External wallets should NOT be authorized signers over OTHER addresses', 49 | isEOA: true, 50 | challenge: 'foo', 51 | challengeSign: 'foo', 52 | signingKeys: [keyA], 53 | authAddr: keyToAddress(keyB), 54 | mockContract: { 55 | authorizedKey: privateToPublic(keyC), 56 | address: keyToAddress(keyB), 57 | errorIsValidSignature: false, 58 | }, 59 | expectedAuthorizedSignerError: false, 60 | expectedAuthorizedSigner: false, 61 | }, 62 | { 63 | title: 64 | 'Smart-contract wallets with a 1-of-1 correct internal key should be authorized signers over their address', 65 | isEOA: false, 66 | challenge: 'foo', 67 | challengeSign: 'foo', 68 | signingKeys: [keyB], 69 | authAddr: keyToAddress(keyA), 70 | mockContract: { 71 | authorizedKey: privateToPublic(keyB), 72 | address: keyToAddress(keyA), 73 | errorIsValidSignature: false, 74 | }, 75 | expectedAuthorizedSignerError: false, 76 | expectedAuthorizedSigner: true, 77 | }, 78 | { 79 | title: 80 | 'Smart-contract wallets with a 1-of-2 (multi-sig) correct internal key should be authorized signers over their address', 81 | isEOA: false, 82 | challenge: 'foo', 83 | challengeSign: 'foo', 84 | signingKeys: [keyB, keyC], 85 | authAddr: keyToAddress(keyA), 86 | mockContract: { 87 | authorizedKey: privateToPublic(keyB), 88 | address: keyToAddress(keyA), 89 | errorIsValidSignature: false, 90 | }, 91 | expectedAuthorizedSignerError: false, 92 | expectedAuthorizedSigner: true, 93 | }, 94 | { 95 | title: 96 | 'Smart-contract wallets with a 1-of-1 incorrect internal key should NOT be authorized signers over their address', 97 | isEOA: false, 98 | challenge: 'foo', 99 | challengeSign: 'foo', 100 | signingKeys: [keyB], 101 | authAddr: keyToAddress(keyA), 102 | mockContract: { 103 | authorizedKey: privateToPublic(keyC), 104 | address: keyToAddress(keyA), 105 | errorIsValidSignature: false, 106 | }, 107 | expectedAuthorizedSignerError: false, 108 | expectedAuthorizedSigner: false, 109 | }, 110 | { 111 | title: 'isAuthorizedSigner should error when smart-contract call errors', 112 | isEOA: false, 113 | challenge: 'foo', 114 | challengeSign: 'foo', 115 | signingKeys: [keyB], 116 | authAddr: keyToAddress(keyA), 117 | mockContract: { 118 | authorizedKey: privateToPublic(keyB), 119 | address: keyToAddress(keyA), 120 | errorIsValidSignature: true, 121 | }, 122 | expectedAuthorizedSignerError: true, 123 | expectedAuthorizedSigner: false, 124 | }, 125 | ]; 126 | 127 | testCases.forEach((test) => 128 | it(test.title, async () => { 129 | const dappAuth = new DappAuth( 130 | new ProviderMock(new ContractMock(test.mockContract)), 131 | ); 132 | 133 | const signatureFunc = test.isEOA 134 | ? signEOAPersonalMessage 135 | : signERC1654PersonalMessage; 136 | 137 | const signatures = `0x${test.signingKeys 138 | .map((signingKey) => 139 | stripHexPrefix( 140 | signatureFunc(test.challengeSign, signingKey, test.authAddr), 141 | ), 142 | ) 143 | .join('')}`; 144 | 145 | let isError = false; 146 | let isAuthorizedSigner = false; 147 | try { 148 | isAuthorizedSigner = await dappAuth.isAuthorizedSigner( 149 | test.challenge, 150 | signatures, 151 | test.authAddr, 152 | ); 153 | } catch (error) { 154 | isError = true; 155 | } 156 | 157 | equal(isError, test.expectedAuthorizedSignerError); 158 | equal(isAuthorizedSigner, test.expectedAuthorizedSigner); 159 | }), 160 | ); 161 | 162 | it('It should decode challenge as utf8 by default when decoding challenges', async function() { 163 | const dappAuth = new DappAuth( 164 | new ProviderMock( 165 | new ContractMock({ 166 | authorizedKey: null, 167 | address: null, 168 | errorIsValidSignature: false, 169 | }), 170 | ), 171 | ); 172 | 173 | const eoaHash = dappAuth._hashEOAPersonalMessage('foo'); 174 | equal( 175 | `0x${eoaHash.toString('hex')}`, 176 | '0x76b2e96714d3b5e6eb1d1c509265430b907b44f72b2a22b06fcd4d96372b8565', 177 | ); 178 | 179 | const scHash = dappAuth._hashSCMessage('foo'); 180 | equal( 181 | `0x${scHash.toString('hex')}`, 182 | '0x41b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d', 183 | ); 184 | }); 185 | 186 | // See https://github.com/MetaMask/eth-sig-util/issues/60 187 | it('It should decode challenge as hex if hex is detected when decoding challenges', async function() { 188 | const dappAuth = new DappAuth( 189 | new ProviderMock( 190 | new ContractMock({ 191 | authorizedKey: null, 192 | address: null, 193 | errorIsValidSignature: false, 194 | }), 195 | ), 196 | ); 197 | 198 | // result if 0xffff is decoded as hex: 13a6aa3102b2d639f36804a2d7c31469618fd7a7907c658a7b2aa91a06e31e47 199 | // result if 0xffff is decoded as utf8: 247aefb5d2e5b17fca61f786c779f7388485460c13e51308f88b2ff84ffa6851 200 | const eoaHash = dappAuth._hashEOAPersonalMessage('0xffff'); 201 | equal( 202 | `0x${eoaHash.toString('hex')}`, 203 | '0x13a6aa3102b2d639f36804a2d7c31469618fd7a7907c658a7b2aa91a06e31e47', 204 | ); 205 | 206 | // result if 0xffff is decoded as hex: 06d41322d79dfed27126569cb9a80eb0967335bf2f3316359d2a93c779fcd38a 207 | // result if 0xffff is decoded as utf8: f0443ea82539c5136844b0a175f544b7ee7bc0fc5ce940bad19f08eaf618af71 208 | const scHash = dappAuth._hashSCMessage('0xffff'); 209 | equal( 210 | `0x${scHash.toString('hex')}`, 211 | '0x06d41322d79dfed27126569cb9a80eb0967335bf2f3316359d2a93c779fcd38a', 212 | ); 213 | }); 214 | 215 | // This test is needed for 100% coverage 216 | it('Invalid signature should fail', async function() { 217 | const dappAuth = new DappAuth( 218 | new ProviderMock( 219 | new ContractMock({ 220 | authorizedKey: null, 221 | address: null, 222 | errorIsValidSignature: false, 223 | }), 224 | ), 225 | ); 226 | 227 | const signatures = '0xinvalid-signature'; 228 | 229 | let isError = false; 230 | let isAuthorizedSigner = false; 231 | try { 232 | isAuthorizedSigner = await dappAuth.isAuthorizedSigner( 233 | 'foo', 234 | signatures, 235 | keyToAddress(keyA), 236 | ); 237 | } catch (error) { 238 | isError = true; 239 | } 240 | 241 | equal(isError, true); 242 | equal(isAuthorizedSigner, false); 243 | }); 244 | }); 245 | 246 | describe('utils', function() { 247 | it('Should remove hex prefix if value is hex prefixed', function() { 248 | const value = 'foo'; 249 | equal(removeHexPrefix(value), 'foo'); 250 | }); 251 | }); 252 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/__tests__/fixtures/getEvmSupport.ts: -------------------------------------------------------------------------------- 1 | export const getEvmSupportList = { 2 | '1': { 3 | chain_id: 1, 4 | name: 'ethereum', 5 | display_name: 'Ethereum', 6 | network_type: 'mainnet', 7 | blocto_service_environment: 'prod', 8 | rpc_endpoint_domains: [ 9 | 'mainnet.infura.io', 10 | 'rpc.ankr.com', 11 | 'cloudflare-eth.com', 12 | ], 13 | }, 14 | '5': { 15 | chain_id: 5, 16 | name: 'ethereum', 17 | display_name: 'Goerli', 18 | network_type: 'testnet', 19 | blocto_service_environment: 'dev', 20 | rpc_endpoint_domains: [ 21 | 'goerli.infura.io', 22 | 'goerli.blockpi.network', 23 | 'rpc.ankr.com', 24 | ], 25 | }, 26 | '10': { 27 | chain_id: 10, 28 | name: 'optimism', 29 | display_name: 'Optimism', 30 | network_type: 'mainnet', 31 | blocto_service_environment: 'prod', 32 | rpc_endpoint_domains: [ 33 | 'optimism-mainnet.infura.io', 34 | 'mainnet.optimism.io', 35 | 'opt-mainnet.g.alchemy.com', 36 | 'optimism.blockpi.network', 37 | 'rpc.ankr.com', 38 | ], 39 | }, 40 | '56': { 41 | chain_id: 56, 42 | name: 'bsc', 43 | display_name: 'BNB Smart Chain', 44 | network_type: 'mainnet', 45 | blocto_service_environment: 'prod', 46 | rpc_endpoint_domains: [ 47 | 'bsc-dataseed.binance.org', 48 | 'bsc-dataseed1.binance.org', 49 | 'bsc-dataseed2.binance.org', 50 | 'bsc-dataseed3.binance.org', 51 | 'bsc-dataseed4.binance.org', 52 | 'bsc-dataseed1.defibit.io', 53 | 'bsc-dataseed2.defibit.io', 54 | 'bsc-dataseed3.defibit.io', 55 | 'bsc-dataseed4.defibit.io', 56 | 'bsc-dataseed1.ninicoin.io', 57 | 'bsc-dataseed2.ninicoin.io', 58 | 'bsc-dataseed3.ninicoin.io', 59 | 'bsc-dataseed4.ninicoin.io', 60 | 'rpc.ankr.com', 61 | ], 62 | }, 63 | '97': { 64 | chain_id: 97, 65 | name: 'bsc', 66 | display_name: 'BNB Smart Chain Testnet', 67 | network_type: 'testnet', 68 | blocto_service_environment: 'dev', 69 | rpc_endpoint_domains: [ 70 | 'data-seed-prebsc-1-s1.binance.org', 71 | 'data-seed-prebsc-2-s1.binance.org', 72 | 'data-seed-prebsc-1-s2.binance.org', 73 | 'data-seed-prebsc-2-s2.binance.org', 74 | 'data-seed-prebsc-1-s3.binance.org', 75 | 'data-seed-prebsc-2-s3.binance.org', 76 | 'rpc.ankr.com', 77 | ], 78 | }, 79 | '137': { 80 | chain_id: 137, 81 | name: 'polygon', 82 | display_name: 'Polygon', 83 | network_type: 'mainnet', 84 | blocto_service_environment: 'prod', 85 | rpc_endpoint_domains: [ 86 | 'polygon-mainnet.infura.io', 87 | 'rpc.ankr.com', 88 | 'polygon-rpc.com', 89 | 'rpc-mainnet.maticvigil.com', 90 | ], 91 | }, 92 | '4200': { 93 | chain_id: 4200, 94 | name: 'merlin', 95 | display_name: 'Merlin', 96 | network_type: 'mainnet', 97 | blocto_service_environment: 'prod', 98 | rpc_endpoint_domains: ['rpc.merlinchain.io', 'merlin.blockpi.network'], 99 | }, 100 | '8453': { 101 | chain_id: 8453, 102 | name: 'base', 103 | display_name: 'Base', 104 | network_type: 'mainnet', 105 | blocto_service_environment: 'prod', 106 | rpc_endpoint_domains: [ 107 | 'base-mainnet.infura.io', 108 | 'base-mainnet.g.alchemy.com', 109 | 'mainnet.base.org', 110 | 'rpc.ankr.com', 111 | 'base.blockpi.network', 112 | '1rpc.io', 113 | ], 114 | }, 115 | '42161': { 116 | chain_id: 42161, 117 | name: 'arbitrum', 118 | display_name: 'Arbitrum', 119 | network_type: 'mainnet', 120 | blocto_service_environment: 'prod', 121 | rpc_endpoint_domains: [ 122 | 'arbitrum-mainnet.infura.io', 123 | 'arb1.arbitrum.io', 124 | 'arb-mainnet.g.alchemy.com', 125 | 'arbitrum.blockpi.network', 126 | 'rpc.ankr.com', 127 | ], 128 | }, 129 | '43113': { 130 | chain_id: 43113, 131 | name: 'avalanche', 132 | display_name: 'Avalanche Fuji', 133 | network_type: 'testnet', 134 | blocto_service_environment: 'dev', 135 | rpc_endpoint_domains: [ 136 | 'api.avax-test.network', 137 | 'avalanche-fuji.infura.io', 138 | 'rpc.ankr.com', 139 | 'ava-testnet.public.blastapi.io', 140 | ], 141 | }, 142 | '43114': { 143 | chain_id: 43114, 144 | name: 'avalanche', 145 | display_name: 'Avalanche', 146 | network_type: 'mainnet', 147 | blocto_service_environment: 'prod', 148 | rpc_endpoint_domains: [ 149 | 'api.avax.network', 150 | 'avalanche-mainnet.infura.io', 151 | 'rpc.ankr.com', 152 | 'ava-mainnet.public.blastapi.io', 153 | 'snowtrace.io', 154 | ], 155 | }, 156 | '80002': { 157 | chain_id: 80002, 158 | name: 'polygon_amoy', 159 | display_name: 'Amoy Testnet', 160 | network_type: 'testnet', 161 | blocto_service_environment: 'dev', 162 | rpc_endpoint_domains: ['rpc-amoy.polygon.technology', 'rpc.ankr.com'], 163 | }, 164 | '81457': { 165 | chain_id: 81457, 166 | name: 'blast', 167 | display_name: 'Blast', 168 | network_type: 'mainnet', 169 | blocto_service_environment: 'prod', 170 | rpc_endpoint_domains: [ 171 | 'rpc.blast.io', 172 | 'rpc.ankr.com', 173 | 'blast.din.dev', 174 | 'blastl2-mainnet.public.blastapi.io', 175 | 'blast.blockpi.network', 176 | ], 177 | }, 178 | '84532': { 179 | chain_id: 84532, 180 | name: 'base_sepolia', 181 | display_name: 'Base Sepolia', 182 | network_type: 'testnet', 183 | blocto_service_environment: 'dev', 184 | rpc_endpoint_domains: [ 185 | 'sepolia.base.org', 186 | 'base-sepolia.blockpi.network', 187 | 'base-sepolia.g.alchemy.com', 188 | 'base-sepolia.infura.io', 189 | 'rpc.ankr.com', 190 | '1rpc.io', 191 | ], 192 | }, 193 | '421614': { 194 | chain_id: 421614, 195 | name: 'arbitrum_sepolia', 196 | display_name: 'Arbitrum Sepolia', 197 | network_type: 'testnet', 198 | blocto_service_environment: 'dev', 199 | rpc_endpoint_domains: [ 200 | 'sepolia-rollup.arbitrum.io/rpc', 201 | 'arbitrum-sepolia.infura.io', 202 | 'arb-sepolia.g.alchemy.com', 203 | 'rpc.ankr.com', 204 | ], 205 | }, 206 | '534351': { 207 | chain_id: 534351, 208 | name: 'scroll_sepolia', 209 | display_name: 'Scroll Sepolia', 210 | network_type: 'testnet', 211 | blocto_service_environment: 'dev', 212 | rpc_endpoint_domains: [ 213 | 'sepolia-rpc.scroll.io', 214 | 'scroll-testnet-public.unifra.io', 215 | 'scroll-sepolia.blockpi.network', 216 | 'rpc.ankr.com', 217 | 'scroll-sepolia.chainstacklabs.com', 218 | 'scroll-public.scroll-testnet.quiknode.pro', 219 | ], 220 | }, 221 | '534352': { 222 | chain_id: 534352, 223 | name: 'scroll', 224 | display_name: 'Scroll', 225 | network_type: 'mainnet', 226 | blocto_service_environment: 'prod', 227 | rpc_endpoint_domains: [ 228 | 'rpc.scroll.io', 229 | 'rpc.ankr.com', 230 | 'rpc-scroll.icecreamswap.com', 231 | 'scroll-mainnet.public.blastapi.io', 232 | 'scroll-mainnet-public.unifra.io', 233 | 'scroll.blockpi.network', 234 | '1rpc.io', 235 | 'scroll-mainnet.chainstacklabs.com', 236 | ], 237 | }, 238 | '686868': { 239 | chain_id: 686868, 240 | name: 'merlin_testnet', 241 | display_name: 'Merlin Testnet', 242 | network_type: 'testnet', 243 | blocto_service_environment: 'dev', 244 | rpc_endpoint_domains: ['testnet-rpc.merlinchain.io'], 245 | }, 246 | '1261120': { 247 | chain_id: 1261120, 248 | name: 'zkatana_sepolia', 249 | display_name: 'Astar zKatana', 250 | network_type: 'testnet', 251 | blocto_service_environment: 'dev', 252 | rpc_endpoint_domains: [ 253 | 'rpc.startale.com/zkatana', 254 | 'rpc.zkatana.gelato.digital', 255 | 'astar-zkatana-rpc.dwellir.com', 256 | ], 257 | }, 258 | '7777777': { 259 | chain_id: 7777777, 260 | name: 'zora', 261 | display_name: 'Zora', 262 | network_type: 'mainnet', 263 | blocto_service_environment: 'prod', 264 | rpc_endpoint_domains: ['rpc.zora.energy'], 265 | }, 266 | '11155111': { 267 | chain_id: 11155111, 268 | name: 'ethereum_sepolia', 269 | display_name: 'Sepolia', 270 | network_type: 'testnet', 271 | blocto_service_environment: 'dev', 272 | rpc_endpoint_domains: [ 273 | 'sepolia.infura.io', 274 | 'rpc.sepolia.dev', 275 | 'rpc.sepolia.org', 276 | 'rpc.sepolia.online', 277 | 'www.sepoliarpc.space', 278 | 'rpc-sepolia.rockx.com', 279 | 'rpc.bordel.wtf/sepolia', 280 | ], 281 | }, 282 | '11155420': { 283 | chain_id: 11155420, 284 | name: 'optimism_sepolia', 285 | display_name: 'Optimism Sepolia', 286 | network_type: 'testnet', 287 | blocto_service_environment: 'dev', 288 | rpc_endpoint_domains: [ 289 | 'optimism-sepolia.infura.io', 290 | 'rpc.ankr.com', 291 | 'sepolia.optimism.io', 292 | 'opt-sepolia.g.alchemy.com', 293 | 'optimism-sepolia.blockpi.network', 294 | ], 295 | }, 296 | '168587773': { 297 | chain_id: 168587773, 298 | name: 'blast_sepolia', 299 | display_name: 'Blast Sepolia', 300 | network_type: 'testnet', 301 | blocto_service_environment: 'dev', 302 | rpc_endpoint_domains: ['sepolia.blast.io', 'blast-sepolia.blockpi.network'], 303 | }, 304 | '999999999': { 305 | chain_id: 999999999, 306 | name: 'zora_sepolia', 307 | display_name: 'Zora Sepolia', 308 | network_type: 'testnet', 309 | blocto_service_environment: 'dev', 310 | rpc_endpoint_domains: ['sepolia.rpc.zora.energy'], 311 | }, 312 | }; 313 | -------------------------------------------------------------------------------- /packages/blocto-sdk/src/__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | import BloctoSDK from '../main'; 2 | import { enableFetchMocks } from 'jest-fetch-mock'; 3 | import { setAccountStorage } from '../lib/storage'; 4 | 5 | beforeAll(() => { 6 | enableFetchMocks(); 7 | fetch.mockResponse((req) => { 8 | if (req.url === 'https://api.blocto.app/networks/evm') { 9 | return new Promise((resolve) => { 10 | resolve({ 11 | status: 200, 12 | body: JSON.stringify({ 13 | networks: [ 14 | { 15 | chain_id: 5, 16 | name: 'ethereum', 17 | display_name: 'Ethereum', 18 | network_type: 'testnet', 19 | blocto_service_environment: 'dev', 20 | rpc_endpoint_domains: [], 21 | }, 22 | { 23 | chain_id: 56, 24 | name: 'bsc', 25 | display_name: 'Smart Chain', 26 | network_type: 'mainnet', 27 | blocto_service_environment: 'prod', 28 | rpc_endpoint_domains: [], 29 | }, 30 | ], 31 | }), 32 | }); 33 | }); 34 | } 35 | return new Promise((resolve) => { 36 | resolve({ 37 | status: 200, 38 | body: JSON.stringify({ 39 | test: 'pass', 40 | }), 41 | }); 42 | }); 43 | }); 44 | setAccountStorage('BLOCTO_SDK', { 45 | code: '123', 46 | accounts: { 47 | aptos: ['0x123'], 48 | }, 49 | evm: { 50 | bsc: ['0x123'], 51 | }, 52 | }); 53 | }); 54 | 55 | describe('Testing BloctoSDK', () => { 56 | test('should be a class', () => { 57 | expect(BloctoSDK).toBeInstanceOf(Function); 58 | }); 59 | }); 60 | 61 | describe('Testing BloctoSDK ethereum provider', () => { 62 | const bloctoSDK = new BloctoSDK({ 63 | ethereum: { 64 | chainId: 56, 65 | rpc: 'https://bsc-dataseed.binance.org', 66 | }, 67 | }); 68 | const ethereum = bloctoSDK.ethereum; 69 | ethereum.setIframe = jest.fn(); 70 | ethereum.responseListener = jest.fn(); 71 | 72 | test('should be a object', () => { 73 | expect(bloctoSDK).toBeInstanceOf(Object); 74 | }); 75 | test('should have ethereum provider', () => { 76 | expect(ethereum).toBeInstanceOf(Object); 77 | }); 78 | test('should have isBlocto', () => { 79 | expect(ethereum.isBlocto).toBe(true); 80 | }); 81 | test('converted chainId should be hexdecimal', () => { 82 | expect(ethereum.chainId).toBe('0x38'); 83 | }); 84 | test('should setup rpc', () => { 85 | expect(ethereum.rpc).toBe('https://bsc-dataseed.binance.org'); 86 | }); 87 | test('should setup _blocto', async () => { 88 | await ethereum.request({ 89 | method:"eth_addEthereumChain", 90 | params: [ 91 | { 92 | chainId: '0xaa36a7', 93 | rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'] 94 | } 95 | ] 96 | }); 97 | expect(ethereum._blocto.networkType).toBe('mainnet'); 98 | }); 99 | test('should request chainId work', async () => { 100 | return ethereum.request({ method: 'eth_chainId' }).then((chainId) => { 101 | expect(chainId).toBe('0x38'); 102 | }); 103 | }); 104 | test('should request eth_estimateUserOperationGas works', async () => { 105 | return ethereum 106 | .request({ method: 'eth_estimateUserOperationGas' }) 107 | .then((response) => { 108 | expect(JSON.parse(fetch.mock.lastCall[1].body).method).toBe( 109 | 'eth_estimateUserOperationGas' 110 | ); 111 | expect(response.test).toBe('pass'); 112 | }); 113 | }); 114 | test('should request personal_sign send right param', async () => { 115 | const exampleMessage = 'Test `personal_sign` message.'; 116 | return ethereum 117 | .request({ 118 | method: 'personal_sign', 119 | params: [exampleMessage, '0x123'], 120 | }) 121 | .then(() => { 122 | expect(fetch.mock.lastCall[0]).toBe( 123 | 'https://wallet-v2.blocto.app/api/bsc/user-signature' 124 | ); 125 | expect(fetch.mock.lastCall[1].body).toBe( 126 | JSON.stringify({ 127 | method: 'personal_sign', 128 | message: 129 | '546573742060706572736f6e616c5f7369676e60206d6573736167652e', 130 | }) 131 | ); 132 | }); 133 | }); 134 | test('should request eth_signTypedData call right api', async () => { 135 | const msgParams = JSON.stringify({ 136 | domain: { 137 | chainId: 56, 138 | name: 'Ether Mail', 139 | verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', 140 | version: '1', 141 | }, 142 | message: { 143 | contents: 'Hello, Bob!', 144 | }, 145 | }); 146 | return ethereum 147 | .request({ 148 | method: 'eth_signTypedData', 149 | params: ['0x123', msgParams], 150 | }) 151 | .then(() => { 152 | expect(fetch.mock.lastCall[0]).toBe( 153 | 'https://wallet-v2.blocto.app/api/bsc/user-signature' 154 | ); 155 | expect(fetch.mock.lastCall[1].body).toBe( 156 | JSON.stringify({ method: 'eth_signTypedData', message: msgParams }) 157 | ); 158 | }); 159 | }); 160 | test('should request eth_sendTransaction call right api', async () => { 161 | return ethereum 162 | .request({ 163 | method: 'eth_sendTransaction', 164 | params: [ 165 | { 166 | from: '0x123', 167 | to: '0x123', 168 | value: '0x29a2241af62c0000', 169 | }, 170 | ], 171 | }) 172 | .then(() => { 173 | expect(fetch.mock.lastCall[0]).toBe( 174 | 'https://wallet-v2.blocto.app/api/bsc/authz' 175 | ); 176 | expect(fetch.mock.lastCall[1].body).toBe( 177 | '[[{"from":"0x123","to":"0x123","value":"0x29a2241af62c0000"}],true]' 178 | ); 179 | }); 180 | }); 181 | test('should request wallet_sendMultiCallTransaction in EIP-1193 way has right payload', async () => { 182 | return ethereum 183 | .request({ 184 | method: 'wallet_sendMultiCallTransaction', 185 | params: [ 186 | [{ 187 | from: '0x123', 188 | to: '0x123', 189 | value: '0x01abc', 190 | }, 191 | { 192 | from: '0x456', 193 | to: '0x456', 194 | value: '0x02def', 195 | }], 196 | false 197 | ], 198 | }) 199 | .then(() => { 200 | expect(fetch.mock.lastCall[0]).toBe( 201 | 'https://wallet-v2.blocto.app/api/bsc/authz' 202 | ); 203 | expect(fetch.mock.lastCall[1].body).toBe( 204 | '[[{"from":"0x123","to":"0x123","value":"0x01abc"},{"from":"0x456","to":"0x456","value":"0x02def"}],false]' 205 | ); 206 | }); 207 | }); 208 | test('should request wallet_sendMultiCallTransaction in Web3 Batch Request way has right payload', async () => { 209 | return ethereum 210 | .sendAsync([ 211 | { 212 | method: 'eth_sendTransaction', 213 | params: [ 214 | { 215 | from: '0x123', 216 | to: '0x123', 217 | value: '0x01abc', 218 | }, 219 | ], 220 | }, 221 | { 222 | method: 'eth_sendTransaction', 223 | params: [ 224 | { 225 | from: '0x456', 226 | to: '0x456', 227 | value: '0x02def', 228 | }, 229 | ], 230 | }, 231 | ]) 232 | .then(() => { 233 | expect(fetch.mock.lastCall[0]).toBe( 234 | 'https://wallet-v2.blocto.app/api/bsc/authz' 235 | ); 236 | expect(fetch.mock.lastCall[1].body).toBe( 237 | '[[{"from":"0x123","to":"0x123","value":"0x01abc"},{"from":"0x456","to":"0x456","value":"0x02def"}],false]' 238 | ); 239 | }); 240 | }); 241 | test('should request eth_sendUserOperation call right api', async () => { 242 | return ethereum 243 | .request({ 244 | method: 'eth_sendUserOperation', 245 | params: [ 246 | { 247 | callData: '0x123', 248 | }, 249 | ], 250 | }) 251 | .then(() => { 252 | expect(fetch.mock.lastCall[0]).toBe( 253 | 'https://wallet-v2.blocto.app/api/bsc/user-operation' 254 | ); 255 | expect(fetch.mock.lastCall[1].body).toBe('[{"callData":"0x123"}]'); 256 | }); 257 | }); 258 | }); 259 | 260 | describe('Testing BloctoSDK providers with appId', () => { 261 | const bloctoSDK = new BloctoSDK({ 262 | ethereum: { 263 | chainId: 56, 264 | rpc: 'https://bsc-dataseed.binance.org', 265 | }, 266 | appId: '6f6b97c5-d97b-4799-8ad7-d7e8426d3369', 267 | }); 268 | const ethereum = bloctoSDK.ethereum; 269 | ethereum.setIframe = jest.fn(); 270 | ethereum.responseListener = jest.fn(); 271 | test('should be a object', () => { 272 | expect(bloctoSDK).toBeInstanceOf(Object); 273 | }); 274 | test('should eth_sendTransaction has right appId in header', async () => { 275 | return ethereum 276 | .request({ 277 | method: 'eth_sendTransaction', 278 | params: [ 279 | { 280 | from: '0x123', 281 | to: '0x123', 282 | value: '0x29a2241af62c0000', 283 | }, 284 | ], 285 | }) 286 | .then(() => { 287 | expect( 288 | fetch.mock.lastCall[1].headers['Blocto-Application-Identifier'] 289 | ).toBe('6f6b97c5-d97b-4799-8ad7-d7e8426d3369'); 290 | expect(fetch.mock.lastCall[0]).toBe( 291 | 'https://wallet-v2.blocto.app/api/bsc/authz' 292 | ); 293 | expect(fetch.mock.lastCall[1].body).toBe( 294 | '[[{"from":"0x123","to":"0x123","value":"0x29a2241af62c0000"}],true]' 295 | ); 296 | }); 297 | }); 298 | }); 299 | -------------------------------------------------------------------------------- /adapters/aptos-wallet-adapter-plugin/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @blocto/aptos-wallet-adapter-plugin 2 | 3 | ## 0.2.11 4 | 5 | ### Patch Changes 6 | 7 | - Updated dependencies [79dade9] 8 | - Updated dependencies [ec87223] 9 | - Updated dependencies [2e2164e] 10 | - @blocto/sdk@0.10.4 11 | 12 | ## 0.2.11-beta.0 13 | 14 | ### Patch Changes 15 | 16 | - Updated dependencies [ec87223] 17 | - @blocto/sdk@0.10.4-beta.0 18 | 19 | ## 0.2.10 20 | 21 | ### Patch Changes 22 | 23 | - Updated dependencies [e066144] 24 | - @blocto/sdk@0.10.3 25 | 26 | ## 0.2.10-beta.0 27 | 28 | ### Patch Changes 29 | 30 | - Updated dependencies [e066144] 31 | - @blocto/sdk@0.10.3-beta.0 32 | 33 | ## 0.2.9 34 | 35 | ### Patch Changes 36 | 37 | - Updated dependencies [bd6b11c] 38 | - Updated dependencies [74abbd7] 39 | - @blocto/sdk@0.10.0 40 | 41 | ## 0.2.9-beta.0 42 | 43 | ### Patch Changes 44 | 45 | - Updated dependencies [74abbd7] 46 | - @blocto/sdk@0.10.0-beta.0 47 | 48 | ## 0.2.8 49 | 50 | ### Patch Changes 51 | 52 | - 48fa07a: fix: handle existedSDK handle window not defined 53 | - Updated dependencies [48fa07a] 54 | - Updated dependencies [4ea8a07] 55 | - @blocto/sdk@0.9.1 56 | 57 | ## 0.2.8-beta.1 58 | 59 | ### Patch Changes 60 | 61 | - 48fa07a: fix: handle existedSDK handle window not defined 62 | - Updated dependencies [48fa07a] 63 | - @blocto/sdk@0.9.1-beta.1 64 | 65 | ## 0.2.8-beta.0 66 | 67 | ### Patch Changes 68 | 69 | - Updated dependencies [4ea8a07] 70 | - @blocto/sdk@0.9.1-beta.0 71 | 72 | ## 0.2.7 73 | 74 | ### Patch Changes 75 | 76 | - b9dac7d: support web3js v4 77 | - 8d0b5bf: enhance in-app-sdk event support 78 | - 00a3832: sendAsync can send another requests 79 | - Updated dependencies [b9dac7d] 80 | - Updated dependencies [8d0b5bf] 81 | - Updated dependencies [55afe21] 82 | - Updated dependencies [3017eb1] 83 | - Updated dependencies [00a3832] 84 | - Updated dependencies [aa28bf6] 85 | - Updated dependencies [d34fca2] 86 | - @blocto/sdk@0.9.0 87 | 88 | ## 0.2.7-beta.1 89 | 90 | ### Patch Changes 91 | 92 | - b9dac7d: support web3js v4 93 | - 00a3832: sendAsync can send another requests 94 | - Updated dependencies [b9dac7d] 95 | - Updated dependencies [55afe21] 96 | - Updated dependencies [3017eb1] 97 | - Updated dependencies [00a3832] 98 | - @blocto/sdk@0.9.0-beta.2 99 | 100 | ## 0.2.7-beta.0 101 | 102 | ### Patch Changes 103 | 104 | - 8d0b5bf: enhance in-app-sdk event support 105 | - Updated dependencies [8d0b5bf] 106 | - @blocto/sdk@0.8.1-beta.0 107 | 108 | ## 0.2.6 109 | 110 | ### Patch Changes 111 | 112 | - Updated dependencies [a4d3fbd] 113 | - @blocto/sdk@0.8.0 114 | 115 | ## 0.2.6-beta.0 116 | 117 | ### Patch Changes 118 | 119 | - Updated dependencies [4835522] 120 | - Updated dependencies [e742f66] 121 | - @blocto/sdk@0.7.1-beta.0 122 | 123 | ## 0.2.5 124 | 125 | ### Patch Changes 126 | 127 | - Updated dependencies [2515a8f] 128 | - Updated dependencies [b40fbed] 129 | - Updated dependencies [4c769f9] 130 | - Updated dependencies [bbf2160] 131 | - Updated dependencies [a3b0243] 132 | - Updated dependencies [1288bd1] 133 | - @blocto/sdk@0.7.0 134 | 135 | ## 0.2.5-beta.0 136 | 137 | ### Patch Changes 138 | 139 | - Updated dependencies [b40fbed] 140 | - Updated dependencies [4c769f9] 141 | - Updated dependencies [bbf2160] 142 | - Updated dependencies [a3b0243] 143 | - Updated dependencies [1288bd1] 144 | - @blocto/sdk@0.7.0-beta.0 145 | 146 | ## 0.2.4 147 | 148 | ### Patch Changes 149 | 150 | - Updated dependencies [21097d9] 151 | - Updated dependencies [e0e8fb7] 152 | - Updated dependencies [6e427b1] 153 | - Updated dependencies [34a23e4] 154 | - Updated dependencies [55f3395] 155 | - Updated dependencies [3ceb547] 156 | - Updated dependencies [21097d9] 157 | - Updated dependencies [21097d9] 158 | - Updated dependencies [21097d9] 159 | - Updated dependencies [21097d9] 160 | - Updated dependencies [494ded1] 161 | - @blocto/sdk@0.6.0 162 | 163 | ## 0.2.4-beta.0 164 | 165 | ### Patch Changes 166 | 167 | - Updated dependencies [e0e8fb7] 168 | - @blocto/sdk@0.6.0-beta.0 169 | 170 | ## 0.2.3 171 | 172 | ### Patch Changes 173 | 174 | - abd96b2: Update aptos dependency to 1.15.0 175 | - Updated dependencies [abd96b2] 176 | - Updated dependencies [fec7693] 177 | - Updated dependencies [dca87b8] 178 | - Updated dependencies [b9f1eca] 179 | - Updated dependencies [2cacc63] 180 | - @blocto/sdk@0.5.5 181 | 182 | ## 0.2.3-beta.1 183 | 184 | ### Patch Changes 185 | 186 | - Update aptos dependency to 1.15.0 187 | - Updated dependencies 188 | - @blocto/sdk@0.5.5-beta.3 189 | 190 | ## 0.2.3-beta.0 191 | 192 | ### Patch Changes 193 | 194 | - Updated dependencies [fec7693] 195 | - @blocto/sdk@0.5.5-beta.0 196 | 197 | ## 0.2.2 198 | 199 | ### Patch Changes 200 | 201 | - Updated dependencies [6ae5c63] 202 | - Updated dependencies [438b66e] 203 | - Updated dependencies [a21d79b] 204 | - @blocto/sdk@0.5.4 205 | 206 | ## 0.2.2-beta.0 207 | 208 | ### Patch Changes 209 | 210 | - Updated dependencies [6ae5c63] 211 | - Updated dependencies [438b66e] 212 | - Updated dependencies [a21d79b] 213 | - @blocto/sdk@0.5.4-beta.0 214 | 215 | ## 0.2.1 216 | 217 | ### Patch Changes 218 | 219 | - f019a52: feat: help disconnect providers when get "incorrect_session_id" event 220 | - 80590d9: Emit accountChanged event if switch chain return different account 221 | - Updated dependencies [f019a52] 222 | - Updated dependencies [80590d9] 223 | - Updated dependencies [2c598f5] 224 | - @blocto/sdk@0.5.1 225 | 226 | ## 0.2.0 227 | 228 | ### Minor Changes 229 | 230 | - 9329e0a: Update core SDK dependency 231 | 232 | ### Patch Changes 233 | 234 | - 22ed496: fix: handle if sendUserOp call before enable 235 | - 2f87cbf: Update dependencies 236 | - 37e7db3: Add support for native ES6 import 237 | - c8a3b32: Fix eth_sendTransaction function 238 | - 8a5b40b: fix: wrong chainId after switch chain 239 | - cd1f781: Move session id to session storage 240 | - 05848f8: Replace rollup polyfill plugin with rollup-plugin-polyfill-node 241 | - Updated dependencies [22ed496] 242 | - Updated dependencies [68e1e82] 243 | - Updated dependencies [2f87cbf] 244 | - Updated dependencies [a83376b] 245 | - Updated dependencies [448c667] 246 | - Updated dependencies [9285453] 247 | - Updated dependencies [d495e61] 248 | - Updated dependencies [a4d99b1] 249 | - Updated dependencies [37e7db3] 250 | - Updated dependencies [652eefb] 251 | - Updated dependencies [17340c0] 252 | - Updated dependencies [c8a3b32] 253 | - Updated dependencies [5ea9bdd] 254 | - Updated dependencies [f078a5f] 255 | - Updated dependencies [e180c58] 256 | - Updated dependencies [c3485b6] 257 | - Updated dependencies [9c2d4bc] 258 | - Updated dependencies [a94fdba] 259 | - Updated dependencies [26cc3e9] 260 | - Updated dependencies [8a5b40b] 261 | - Updated dependencies [9630860] 262 | - Updated dependencies [cd1f781] 263 | - Updated dependencies [7830573] 264 | - Updated dependencies [17cf594] 265 | - Updated dependencies [05848f8] 266 | - @blocto/sdk@0.5.0 267 | 268 | ## 0.2.0-beta.5 269 | 270 | ### Patch Changes 271 | 272 | - 22ed496: fix: handle if sendUserOp call before enable 273 | - Updated dependencies [22ed496] 274 | - @blocto/sdk@0.5.0-beta.14 275 | 276 | ## 0.2.0-beta.4 277 | 278 | ### Patch Changes 279 | 280 | - 8a5b40b: fix: wrong chainId after switch chain 281 | - Updated dependencies [8a5b40b] 282 | - @blocto/sdk@0.5.0-beta.12 283 | 284 | ## 0.2.0-beta.3 285 | 286 | ### Patch Changes 287 | 288 | - Replace rollup polyfill plugin with rollup-plugin-polyfill-node 289 | - Updated dependencies 290 | - @blocto/sdk@0.5.0-beta.11 291 | 292 | ## 0.2.0-beta.2 293 | 294 | ### Patch Changes 295 | 296 | - Add support for native ES6 import 297 | - Updated dependencies 298 | - @blocto/sdk@0.5.0-beta.10 299 | 300 | ## 0.2.0-beta.1 301 | 302 | ### Minor Changes 303 | 304 | - Update core SDK dependency 305 | 306 | ## 0.1.9-beta.0 307 | 308 | ### Patch Changes 309 | 310 | - 2f87cbf: Update dependencies 311 | - c8a3b32: Fix eth_sendTransaction function 312 | - cd1f781: Move session id to session storage 313 | - Updated dependencies [68e1e82] 314 | - Updated dependencies [2f87cbf] 315 | - Updated dependencies [448c667] 316 | - Updated dependencies [d495e61] 317 | - Updated dependencies [c8a3b32] 318 | - Updated dependencies [f078a5f] 319 | - Updated dependencies [e180c58] 320 | - Updated dependencies [26cc3e9] 321 | - Updated dependencies [0351fca] 322 | - Updated dependencies [cd1f781] 323 | - Updated dependencies [7830573] 324 | - @blocto/sdk@0.5.0-beta.0 325 | 326 | ## 0.1.9 327 | 328 | ### Patch Changes 329 | 330 | - 17ead9c: aptos login condition 331 | - Updated dependencies [17ead9c] 332 | - @blocto/sdk@0.4.9 333 | 334 | ## 0.1.8 335 | 336 | ### Patch Changes 337 | 338 | - ebfb0da: Fix TypeScript types and eslint errors 339 | - Updated dependencies [ebfb0da] 340 | - Updated dependencies [0570b1e] 341 | - @blocto/sdk@0.4.7 342 | 343 | ## 0.1.8-beta.0 344 | 345 | ### Patch Changes 346 | 347 | - ebfb0da: Fix TypeScript types and eslint errors 348 | - Updated dependencies [ebfb0da] 349 | - @blocto/sdk@0.4.7-beta.0 350 | 351 | ## 0.1.7 352 | 353 | ### Patch Changes 354 | 355 | - 76a1b11: Add goerli support 356 | - Updated dependencies [76a1b11] 357 | - @blocto/sdk@0.4.6 358 | 359 | ## 0.1.6 360 | 361 | ### Patch Changes 362 | 363 | - 8313b19: Format signing message payload for Aptos 364 | - 8188f4f: Remove invariant lib prevent process undefined 365 | - 4da58d8: Fix incorrect session id error when the user logs in/out on the different chains 366 | - 655d1ca: Fix the formatting funciton for Aptos signing message 367 | - Updated dependencies [8313b19] 368 | - Updated dependencies [6e2cd2c] 369 | - Updated dependencies [8188f4f] 370 | - Updated dependencies [4da58d8] 371 | - Updated dependencies [655d1ca] 372 | - @blocto/sdk@0.4.5 373 | 374 | ## 0.1.6-beta.0 375 | 376 | ### Patch Changes 377 | 378 | - 8188f4f: Remove invariant lib prevent process undefined 379 | - Updated dependencies [8188f4f] 380 | - @blocto/sdk@0.4.5-beta.0 381 | 382 | ## 0.1.5 383 | 384 | ### Patch Changes 385 | 386 | - 8285743: Migrate with monorepo and changeset 387 | - 53fbf7f: Changed to newest @blocto/sdk dependencies 388 | - Updated dependencies [f45f39e] 389 | - Updated dependencies [8285743] 390 | - Updated dependencies [4cd7b21] 391 | - @blocto/sdk@0.4.4 392 | 393 | ## 0.1.5-beta.1 394 | 395 | ### Patch Changes 396 | 397 | - 53fbf7f: Changed to newest @blocto/sdk dependencies 398 | 399 | ## 0.1.5-beta.0 400 | 401 | ### Patch Changes 402 | 403 | - 8285743: Migrate with monorepo and changeset 404 | - Updated dependencies [8285743] 405 | - @blocto/sdk@0.4.4-beta.0 406 | --------------------------------------------------------------------------------