getTurboModule(
27 | const std::string &name,
28 | const JavaTurboModule::InitParams ¶ms) override;
29 |
30 | /**
31 | * Test-only method. Allows user to verify whether a TurboModule can be
32 | * created by instances of this class.
33 | */
34 | bool canCreateTurboModule(const std::string &name);
35 | };
36 |
37 | } // namespace react
38 | } // namespace facebook
39 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/src/main/java/com/example/newarchitecture/components/MainComponentsRegistry.java:
--------------------------------------------------------------------------------
1 | package com.example.newarchitecture.components;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.proguard.annotations.DoNotStrip;
5 | import com.facebook.react.fabric.ComponentFactory;
6 | import com.facebook.soloader.SoLoader;
7 |
8 | /**
9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a
10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
11 | * folder for you).
12 | *
13 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
14 | * `newArchEnabled` property). Is ignored otherwise.
15 | */
16 | @DoNotStrip
17 | public class MainComponentsRegistry {
18 | static {
19 | SoLoader.loadLibrary("fabricjni");
20 | }
21 |
22 | @DoNotStrip private final HybridData mHybridData;
23 |
24 | @DoNotStrip
25 | private native HybridData initHybrid(ComponentFactory componentFactory);
26 |
27 | @DoNotStrip
28 | private MainComponentsRegistry(ComponentFactory componentFactory) {
29 | mHybridData = initHybrid(componentFactory);
30 | }
31 |
32 | @DoNotStrip
33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) {
34 | return new MainComponentsRegistry(componentFactory);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/examples/vue/src/stores/user.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import type { RpcInterfaces } from '@proton/js'
3 | import * as SDK from '@/webSdk'
4 |
5 | export const useUserStore = defineStore('user', {
6 | state: () => ({
7 | actor: '',
8 | permission: '',
9 | accountData: undefined as RpcInterfaces.UserInfo | undefined
10 | }),
11 | actions: {
12 | async login () {
13 | this.clear()
14 | await SDK.login()
15 |
16 | if (SDK.session) {
17 | if (SDK.session.auth) {
18 | this.actor = SDK.session.auth.actor.toString()
19 | this.permission = SDK.session.auth.permission.toString()
20 | this.accountData = await SDK.getProtonAvatar(this.actor)
21 | }
22 | }
23 | },
24 |
25 | async reconnect () {
26 | this.clear()
27 |
28 | await SDK.reconnect()
29 |
30 | if (SDK.session && SDK.session.auth) {
31 | this.actor = SDK.session.auth.actor.toString()
32 | this.permission = SDK.session.auth.permission.toString()
33 | }
34 | },
35 |
36 | async logout () {
37 | await SDK.logout()
38 | this.clear()
39 | },
40 |
41 | async transfer ({ to, amount }: { to: string; amount: string; }) {
42 | await SDK.transfer({ to, amount })
43 | },
44 |
45 | clear() {
46 | this.actor = ''
47 | this.permission = ''
48 | }
49 | },
50 | })
51 |
--------------------------------------------------------------------------------
/examples/react/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/proton-browser-transport/src/qrcode/index.ts:
--------------------------------------------------------------------------------
1 | import ErrorCorrectLevel from './ErrorCorrectLevel'
2 | import QRCode from './QRCode'
3 |
4 | interface Rect {
5 | x: number
6 | y: number
7 | width: number
8 | height: number
9 | }
10 |
11 | /**
12 | * Generate QR SVG
13 | * @author Johan Nordberg
14 | */
15 | export default function generate(text: string, level: 'L' | 'M' | 'Q' | 'H' = 'L', version = -1) {
16 | const qr = new QRCode(version, ErrorCorrectLevel[level])
17 | const rects: Rect[] = []
18 |
19 | qr.addData(text)
20 | qr.make()
21 |
22 | const rows = qr.modules
23 | const size = rows.length
24 |
25 | for (const [y, row] of rows.entries()) {
26 | let rect: Rect | undefined
27 | for (const [x, on] of row.entries()) {
28 | if (on) {
29 | if (!rect) rect = {x, y, width: 0, height: 1}
30 | rect.width++
31 | } else {
32 | if (rect && rect.width > 0) {
33 | rects.push(rect)
34 | }
35 | rect = undefined
36 | }
37 | }
38 | if (rect && rect.width > 0) {
39 | rects.push(rect)
40 | }
41 | }
42 |
43 | const svg: string[] = [`')
48 |
49 | return 'data:image/svg+xml;base64,' + btoa(svg.join(''))
50 | }
51 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/examples/react-native/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "test": "jest",
10 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
11 | },
12 | "dependencies": {
13 | "@proton/react-native-sdk": "workspace:^",
14 | "@react-native-async-storage/async-storage": "^2.2.0",
15 | "react": "18.1.0",
16 | "react-native": "0.70.10",
17 | "react-native-get-random-values": "^1.11.0"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.12.9",
21 | "@babel/runtime": "^7.12.5",
22 | "@react-native-community/eslint-config": "^2.0.0",
23 | "@tsconfig/react-native": "^2.0.2",
24 | "@types/jest": "^26.0.23",
25 | "@types/react": "^18.0.21",
26 | "@types/react-native": "^0.70.6",
27 | "@types/react-test-renderer": "^18.0.0",
28 | "@typescript-eslint/eslint-plugin": "^5.37.0",
29 | "@typescript-eslint/parser": "^5.37.0",
30 | "babel-jest": "^26.6.3",
31 | "eslint": "^7.32.0",
32 | "jest": "^26.6.3",
33 | "metro-react-native-babel-preset": "0.72.3",
34 | "react-test-renderer": "18.1.0",
35 | "typescript": "^4.8.3"
36 | },
37 | "jest": {
38 | "preset": "react-native",
39 | "moduleFileExtensions": [
40 | "ts",
41 | "tsx",
42 | "js",
43 | "jsx",
44 | "json",
45 | "node"
46 | ]
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.example",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.example",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/examples/svelte/src/lib/userState.ts:
--------------------------------------------------------------------------------
1 | import { writable, get } from 'svelte/store';
2 | import * as SDK from './webSdk';
3 | import type { RpcInterfaces } from '@proton/js';
4 |
5 | export const actor = writable('');
6 | export const permission = writable('');
7 | export const avatar = writable('');
8 |
9 | const clear = () => {
10 | actor.set('');
11 | permission.set('');
12 | avatar.set('');
13 | };
14 |
15 | const getAvatar = (accountData: RpcInterfaces.UserInfo | undefined) => {
16 | const avatar = accountData && accountData.avatar;
17 |
18 | if (avatar) {
19 | if (avatar.indexOf('/9j/') !== -1) {
20 | return `data:image/jpeg;base64,${avatar}`;
21 | } else if (avatar.indexOf('iVBORw0KGgo') !== -1) {
22 | return `data:image/png;base64,${avatar}`;
23 | }
24 | }
25 |
26 | return 'https://explorer.xprnetwork.org/img/proton_avatar.png';
27 | };
28 |
29 | export const login = async (reconnect: boolean = false) => {
30 | clear();
31 |
32 | if (reconnect) {
33 | await SDK.reconnect();
34 | } else {
35 | await SDK.login();
36 | }
37 |
38 | if (SDK.session && SDK.session.auth) {
39 | actor.set(SDK.session!.auth.actor.toString());
40 | permission.set(SDK.session!.auth.permission.toString());
41 |
42 | const userInfo = await SDK.getProtonAvatar(get(actor));
43 | avatar.set(getAvatar(userInfo));
44 | }
45 | };
46 |
47 | export const logout = async () => {
48 | await SDK.logout();
49 | clear();
50 | };
51 |
52 | export const transfer = async ({ to, amount }: { to: string; amount: string }) => {
53 | await SDK.transfer({
54 | to,
55 | amount
56 | });
57 | };
58 |
--------------------------------------------------------------------------------
/packages/proton-link/src/errors.ts:
--------------------------------------------------------------------------------
1 | import type {LinkSession} from './link-session'
2 |
3 | /**
4 | * Error codes. Accessible using the `code` property on errors thrown by [[Link]] and [[LinkSession]].
5 | * - `E_DELIVERY`: Unable to route message to wallet.
6 | * - `E_TIMEOUT`: Request was delivered but user/wallet didn't respond in time.
7 | * - `E_CANCEL`: The [[LinkTransport]] canceled the request.
8 | * - `E_IDENTITY`: Identity proof failed to verify.
9 | */
10 | export type LinkErrorCode = 'E_DELIVERY' | 'E_TIMEOUT' | 'E_CANCEL' | 'E_IDENTITY'
11 |
12 | /**
13 | * Error that is thrown if a [[LinkTransport]] cancels a request.
14 | * @internal
15 | */
16 | export class CancelError extends Error {
17 | public code = 'E_CANCEL'
18 | constructor(reason?: string) {
19 | super(`Request cancelled ${reason ? '(' + reason + ')' : ''}`)
20 | }
21 | }
22 |
23 | /**
24 | * Error that is thrown if an identity request fails to verify.
25 | * @internal
26 | */
27 | export class IdentityError extends Error {
28 | public code = 'E_IDENTITY'
29 | constructor(reason?: string) {
30 | super(`Unable to verify identity ${reason ? '(' + reason + ')' : ''}`)
31 | }
32 | }
33 |
34 | /**
35 | * Error originating from a [[LinkSession]].
36 | * @internal
37 | */
38 | export class SessionError extends Error {
39 | public code: 'E_DELIVERY' | 'E_TIMEOUT'
40 | public session: LinkSession
41 | constructor(reason: string, code: 'E_DELIVERY' | 'E_TIMEOUT', session: LinkSession) {
42 | super(reason)
43 | this.code = code
44 | this.session = session
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/examples/react-native/ios/Podfile:
--------------------------------------------------------------------------------
1 | require_relative '../node_modules/react-native/scripts/react_native_pods'
2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | platform :ios, '12.4'
5 | install! 'cocoapods', :deterministic_uuids => false
6 |
7 | target 'example' do
8 | config = use_native_modules!
9 |
10 | # Flags change depending on the env values.
11 | flags = get_default_flags()
12 |
13 | use_react_native!(
14 | :path => config[:reactNativePath],
15 | # Hermes is now enabled by default. Disable by setting this flag to false.
16 | # Upcoming versions of React Native may rely on get_default_flags(), but
17 | # we make it explicit here to aid in the React Native upgrade process.
18 | :hermes_enabled => true,
19 | :fabric_enabled => flags[:fabric_enabled],
20 | # Enables Flipper.
21 | #
22 | # Note that if you have use_frameworks! enabled, Flipper will not work and
23 | # you should disable the next line.
24 | :flipper_configuration => FlipperConfiguration.enabled,
25 | # An absolute path to your application root.
26 | :app_path => "#{Pod::Config.instance.installation_root}/.."
27 | )
28 |
29 | target 'exampleTests' do
30 | inherit! :complete
31 | # Pods for testing
32 | end
33 |
34 | post_install do |installer|
35 | react_native_post_install(
36 | installer,
37 | # Set `mac_catalyst_enabled` to `true` in order to apply patches
38 | # necessary for Mac Catalyst builds
39 | :mac_catalyst_enabled => false
40 | )
41 | __apply_Xcode_12_5_M1_post_install_workaround(installer)
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/packages/proton-signing-request/eslint.config.ts:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import tseslint from 'typescript-eslint'
4 | import {defineConfig, globalIgnores} from 'eslint/config'
5 | import prettier from 'eslint-plugin-prettier/recommended'
6 |
7 | export default defineConfig([
8 | globalIgnores(['lib/*', 'node_modules/**/*']),
9 | {
10 | files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
11 | plugins: {js},
12 | extends: ['js/recommended'],
13 | languageOptions: {
14 | globals: {...globals.browser, ...globals.node, NodeJS: true},
15 | parserOptions: {
16 | tsconfigRootDir: __dirname,
17 | },
18 | },
19 | },
20 | tseslint.configs.recommended,
21 | prettier,
22 | {
23 | rules: {
24 | 'prettier/prettier': 'warn',
25 | 'no-console': 'warn',
26 |
27 | 'sort-imports': [
28 | 'warn',
29 | {
30 | ignoreCase: true,
31 | ignoreDeclarationSort: true,
32 | },
33 | ],
34 | '@typescript-eslint/explicit-module-boundary-types': 'off',
35 | '@typescript-eslint/no-explicit-any': 'off',
36 | '@typescript-eslint/no-namespace': 'off',
37 | '@typescript-eslint/no-non-null-assertion': 'off',
38 | '@typescript-eslint/no-empty-function': 'off',
39 | 'no-inner-declarations': 'off',
40 | 'no-unused-vars': [
41 | 'warn',
42 | {
43 | argsIgnorePattern: '^_',
44 | },
45 | ],
46 | '@typescript-eslint/no-unused-vars': [
47 | 'warn',
48 | {
49 | argsIgnorePattern: '^_',
50 | },
51 | ],
52 | },
53 | }
54 | ])
55 |
--------------------------------------------------------------------------------
/packages/proton-react-native-sdk/eslint.config.ts:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import tseslint from 'typescript-eslint'
4 | import {defineConfig, globalIgnores} from 'eslint/config'
5 | import prettier from 'eslint-plugin-prettier/recommended'
6 |
7 | export default defineConfig([
8 | globalIgnores(['lib/*', 'node_modules/**/*']),
9 | {
10 | files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
11 | plugins: {js},
12 | extends: ['js/recommended'],
13 | languageOptions: {
14 | globals: {...globals.browser, ...globals.node, NodeJS: true},
15 | parserOptions: {
16 | tsconfigRootDir: __dirname,
17 | },
18 | },
19 | },
20 | tseslint.configs.recommended,
21 | prettier,
22 | {
23 | rules: {
24 | 'prettier/prettier': 'warn',
25 | 'no-console': 'warn',
26 |
27 | 'sort-imports': [
28 | 'warn',
29 | {
30 | ignoreCase: true,
31 | ignoreDeclarationSort: true,
32 | },
33 | ],
34 | '@typescript-eslint/explicit-module-boundary-types': 'off',
35 | '@typescript-eslint/no-explicit-any': 'off',
36 | '@typescript-eslint/no-namespace': 'off',
37 | '@typescript-eslint/no-non-null-assertion': 'off',
38 | '@typescript-eslint/no-empty-function': 'off',
39 | 'no-inner-declarations': 'off',
40 | 'no-unused-vars': [
41 | 'warn',
42 | {
43 | argsIgnorePattern: '^_',
44 | },
45 | ],
46 | '@typescript-eslint/no-unused-vars': [
47 | 'warn',
48 | {
49 | argsIgnorePattern: '^_',
50 | },
51 | ],
52 | },
53 | }
54 | ])
55 |
--------------------------------------------------------------------------------
/packages/proton-react-native-sdk/src/transport.ts:
--------------------------------------------------------------------------------
1 | import {LinkSession, LinkTransport} from '@proton/link'
2 | import {SigningRequest} from '@proton/signing-request'
3 | import {Linking} from 'react-native'
4 |
5 | export interface ReactNativeTransportOptions {
6 | /** Requesting account of the dapp */
7 | requestAccount: string
8 |
9 | /** Return url to the original app */
10 | getReturnUrl(): string
11 | }
12 |
13 | export default class ReactNativeTransport implements LinkTransport {
14 | private requestAccount: string
15 | private getReturnUrl: () => string
16 |
17 | constructor(public readonly options: ReactNativeTransportOptions) {
18 | this.requestAccount = options.requestAccount
19 | this.getReturnUrl = options.getReturnUrl
20 | }
21 |
22 | public onRequest(request: SigningRequest, _cancel: (reason: string | Error) => void) {
23 | const deviceRequest = request.clone()
24 | deviceRequest.setInfoKey('same_device', true)
25 | deviceRequest.setInfoKey('return_path', this.getReturnUrl())
26 |
27 | if (this.requestAccount.length > 0) {
28 | request.setInfoKey('req_account', this.requestAccount)
29 | deviceRequest.setInfoKey('req_account', this.requestAccount)
30 | }
31 |
32 | const sameDeviceUri = deviceRequest.encode(true, false)
33 | Linking.openURL(sameDeviceUri)
34 | }
35 |
36 | public onSessionRequest(
37 | _session: LinkSession,
38 | request: SigningRequest,
39 | _cancel: (reason: string | Error) => void
40 | ) {
41 | request.setInfoKey('return_path', this.getReturnUrl())
42 |
43 | const scheme = request.getScheme()
44 | Linking.openURL(`${scheme}://link`)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp:
--------------------------------------------------------------------------------
1 | #include "MainApplicationTurboModuleManagerDelegate.h"
2 | #include "MainApplicationModuleProvider.h"
3 |
4 | namespace facebook {
5 | namespace react {
6 |
7 | jni::local_ref
8 | MainApplicationTurboModuleManagerDelegate::initHybrid(
9 | jni::alias_ref) {
10 | return makeCxxInstance();
11 | }
12 |
13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() {
14 | registerHybrid({
15 | makeNativeMethod(
16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
17 | makeNativeMethod(
18 | "canCreateTurboModule",
19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
20 | });
21 | }
22 |
23 | std::shared_ptr
24 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
25 | const std::string &name,
26 | const std::shared_ptr &jsInvoker) {
27 | // Not implemented yet: provide pure-C++ NativeModules here.
28 | return nullptr;
29 | }
30 |
31 | std::shared_ptr
32 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
33 | const std::string &name,
34 | const JavaTurboModule::InitParams ¶ms) {
35 | return MainApplicationModuleProvider(name, params);
36 | }
37 |
38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
39 | const std::string &name) {
40 | return getTurboModule(name, nullptr) != nullptr ||
41 | getTurboModule(name, {.moduleName = name}) != nullptr;
42 | }
43 |
44 | } // namespace react
45 | } // namespace facebook
46 |
--------------------------------------------------------------------------------
/packages/proton-signing-request/Makefile:
--------------------------------------------------------------------------------
1 | SRC_FILES := $(shell find src -name '*.ts')
2 | BIN := ./node_modules/.bin
3 |
4 | lib: ${SRC_FILES} package.json tsconfig.json node_modules rollup.config.js
5 | @${BIN}/rollup -c && touch lib
6 |
7 | .PHONY: test
8 | test: node_modules
9 | @TS_NODE_PROJECT='./test/tsconfig.json' ${BIN}/mocha -r ts-node/register --extension ts test/*.ts --grep '$(grep)'
10 |
11 | .PHONY: coverage
12 | coverage: node_modules
13 | @TS_NODE_PROJECT='./test/tsconfig.json' ${BIN}/nyc --reporter=html ${BIN}/mocha -r ts-node/register --extension ts test/*.ts -R nyan && open coverage/index.html
14 |
15 | .PHONY: lint
16 | lint: node_modules
17 | @${BIN}/eslint src --ext .ts --fix
18 |
19 | .PHONY: ci-test
20 | ci-test: node_modules
21 | @TS_NODE_PROJECT='./test/tsconfig.json' ${BIN}/nyc --reporter=text ${BIN}/mocha -r ts-node/register --extension ts test/*.ts -R list
22 |
23 | .PHONY: ci-lint
24 | ci-lint: node_modules
25 | @${BIN}/eslint src --ext .ts --max-warnings 0 --format unix && echo "Ok"
26 |
27 | node_modules:
28 | yarn install --non-interactive --frozen-lockfile --ignore-scripts
29 |
30 | .PHONY: publish
31 | publish: | distclean node_modules
32 | @git diff-index --quiet HEAD || (echo "Uncommitted changes, please commit first" && exit 1)
33 | @git fetch origin && git diff origin/master --quiet || (echo "Changes not pushed to origin, please push first" && exit 1)
34 | @yarn config set version-tag-prefix "" && yarn config set version-git-message "Version %s"
35 | @yarn publish && git push && git push --tags
36 |
37 | .PHONY: clean
38 | clean:
39 | rm -rf lib/ coverage/
40 |
41 | .PHONY: distclean
42 | distclean: clean
43 | rm -rf node_modules/
44 |
--------------------------------------------------------------------------------
/examples/angular/README.md:
--------------------------------------------------------------------------------
1 | # Proton Web SDK - Angular Example
2 |
3 | Small boilerplate to get started with Proton on Angular
4 |
5 | ## Development server
6 |
7 | To start a local development server, run:
8 |
9 | ```bash
10 | ng serve
11 | ```
12 |
13 | Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
14 |
15 | ## Code scaffolding
16 |
17 | Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
18 |
19 | ```bash
20 | ng generate component component-name
21 | ```
22 |
23 | For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
24 |
25 | ```bash
26 | ng generate --help
27 | ```
28 |
29 | ## Building
30 |
31 | To build the project run:
32 |
33 | ```bash
34 | ng build
35 | ```
36 |
37 | This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
38 |
39 | ## Running unit tests
40 |
41 | To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
42 |
43 | ```bash
44 | ng test
45 | ```
46 |
47 | ## Running end-to-end tests
48 |
49 | For end-to-end (e2e) testing, run:
50 |
51 | ```bash
52 | ng e2e
53 | ```
54 |
55 | Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
56 |
57 | ## Additional Resources
58 |
59 | For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
60 |
--------------------------------------------------------------------------------
/packages/proton-browser-transport/src/qrcode/Polynomial.ts:
--------------------------------------------------------------------------------
1 | import math from './math'
2 |
3 | export default class QRPolynomial {
4 | num: number[]
5 | constructor(num, shift) {
6 | if (num.length == undefined) {
7 | throw new Error(num.length + '/' + shift)
8 | }
9 |
10 | let offset = 0
11 |
12 | while (offset < num.length && num[offset] == 0) {
13 | offset++
14 | }
15 |
16 | this.num = new Array(num.length - offset + shift)
17 | for (let i = 0; i < num.length - offset; i++) {
18 | this.num[i] = num[i + offset]
19 | }
20 | }
21 |
22 | get(index: string | number) {
23 | return this.num[index]
24 | }
25 |
26 | getLength() {
27 | return this.num.length
28 | }
29 |
30 | multiply(e: {getLength: () => number; get: (_: number) => any}) {
31 | const num = new Array(this.getLength() + e.getLength() - 1)
32 |
33 | for (let i = 0; i < this.getLength(); i++) {
34 | for (let j = 0; j < e.getLength(); j++) {
35 | num[i + j] ^= math.gexp(math.glog(this.get(i)) + math.glog(e.get(j)))
36 | }
37 | }
38 |
39 | return new QRPolynomial(num, 0)
40 | }
41 |
42 | mod(e: {getLength: () => number; get: (_: number) => any}) {
43 | if (this.getLength() - e.getLength() < 0) {
44 | return this
45 | }
46 |
47 | const ratio = math.glog(this.get(0)) - math.glog(e.get(0))
48 |
49 | const num = new Array(this.getLength())
50 |
51 | for (let i = 0; i < this.getLength(); i++) {
52 | num[i] = this.get(i)
53 | }
54 |
55 | for (let i = 0; i < e.getLength(); i++) {
56 | num[i] ^= math.gexp(math.glog(e.get(i)) + ratio)
57 | }
58 |
59 | // recursive call
60 | return new QRPolynomial(num, 0).mod(e)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/packages/proton-web-sdk/src/types.ts:
--------------------------------------------------------------------------------
1 | import type {Link, LinkOptions, LinkSession, LinkStorage, LoginResult} from '@proton/link'
2 | import type {BrowserTransportOptions} from '@proton/browser-transport'
3 | import type {ProtonWebLink} from './links/protonWeb'
4 |
5 | type PartialBy = Omit & Partial>
6 |
7 | export interface CustomStyleOptions {
8 | modalBackgroundColor?: string
9 | logoBackgroundColor?: string
10 | isLogoRound?: boolean
11 | optionBackgroundColor?: string
12 | optionFontColor?: string
13 | primaryFontColor?: string
14 | secondaryFontColor?: string
15 | linkColor?: string
16 | }
17 |
18 | export interface SelectorOptions {
19 | appName?: string
20 | appLogo?: string
21 | walletType?: string
22 | enabledWalletTypes?: string[]
23 | dialogRootNode?: HTMLElement | string
24 | customStyleOptions?: CustomStyleOptions
25 | }
26 |
27 | export type LocalLinkOptions = PartialBy & {
28 | endpoints: string[]
29 | storage?: LinkStorage
30 | storagePrefix?: string
31 | restoreSession?: boolean
32 | testUrl?: string
33 | }
34 |
35 | export interface ConnectWalletArgs {
36 | linkOptions: LocalLinkOptions
37 | transportOptions?: BrowserTransportOptions
38 | selectorOptions?: SelectorOptions
39 | }
40 |
41 | export interface ConnectWalletRet {
42 | session?: LinkSession
43 | link?: ProtonWebLink | Link
44 | loginResult?: LoginResult
45 | error?: any
46 | }
47 |
48 | export interface WalletItem {
49 | key: string
50 | value: string
51 | }
52 |
53 | export interface LoginOptions {
54 | selectorOptions: SelectorOptions
55 | linkOptions: LocalLinkOptions
56 | transportOptions: BrowserTransportOptions
57 | }
58 |
--------------------------------------------------------------------------------
/packages/proton-link/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 Greymass Inc. All Rights Reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without modification,
4 | are permitted provided that the following conditions are met:
5 |
6 | 1. Redistribution of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | 2. Redistribution in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors
14 | may be used to endorse or promote products derived from this software without
15 | specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26 | OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 | YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT DESIGNED, LICENSED OR INTENDED FOR USE
29 | IN THE DESIGN, CONSTRUCTION, OPERATION OR MAINTENANCE OF ANY MILITARY FACILITY.
30 |
--------------------------------------------------------------------------------
/packages/proton-browser-transport/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 Greymass Inc. All Rights Reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without modification,
4 | are permitted provided that the following conditions are met:
5 |
6 | 1. Redistribution of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | 2. Redistribution in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors
14 | may be used to endorse or promote products derived from this software without
15 | specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26 | OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 | YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT DESIGNED, LICENSED OR INTENDED FOR USE
29 | IN THE DESIGN, CONSTRUCTION, OPERATION OR MAINTENANCE OF ANY MILITARY FACILITY.
30 |
--------------------------------------------------------------------------------
/packages/proton-react-native-sdk/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs
4 | "include": [
5 | "src",
6 | "types"
7 | ],
8 | "compilerOptions": {
9 | "module": "esnext",
10 | "lib": [
11 | "dom",
12 | "esnext"
13 | ],
14 | "importHelpers": true,
15 | // output .d.ts declaration files for consumers
16 | "declaration": true,
17 | // output .js.map sourcemap files for consumers
18 | "sourceMap": true,
19 | // match output dir to input dir. e.g. dist/index instead of dist/src/index
20 | "rootDir": "./src",
21 | "declarationDir": "./lib/types",
22 | // stricter type-checking for stronger correctness. Recommended by TS
23 | "strict": true,
24 | // linter checks for common issues
25 | "noImplicitReturns": true,
26 | "noFallthroughCasesInSwitch": true,
27 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative
28 | "noUnusedLocals": true,
29 | "noUnusedParameters": true,
30 | // use Node's module resolution algorithm, instead of the legacy TS one
31 | "moduleResolution": "node",
32 | // transpile JSX to React.createElement
33 | "jsx": "react",
34 | // interop between ESM and CJS modules. Recommended by TS
35 | "esModuleInterop": true,
36 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS
37 | "skipLibCheck": true,
38 | // error out if import and file system have a casing mismatch. Recommended by TS
39 | "forceConsistentCasingInFileNames": true,
40 | // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc`
41 | "noEmit": true,
42 | "outDir": "./lib"
43 | }
44 | }
--------------------------------------------------------------------------------
/packages/proton-web-sdk/src/views/Header.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
22 |
23 |
63 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/src/main/java/com/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.ReactRootView;
6 |
7 | public class MainActivity extends ReactActivity {
8 |
9 | /**
10 | * Returns the name of the main component registered from JavaScript. This is used to schedule
11 | * rendering of the component.
12 | */
13 | @Override
14 | protected String getMainComponentName() {
15 | return "example";
16 | }
17 |
18 | /**
19 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
20 | * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
21 | * (Paper).
22 | */
23 | @Override
24 | protected ReactActivityDelegate createReactActivityDelegate() {
25 | return new MainActivityDelegate(this, getMainComponentName());
26 | }
27 |
28 | public static class MainActivityDelegate extends ReactActivityDelegate {
29 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
30 | super(activity, mainComponentName);
31 | }
32 |
33 | @Override
34 | protected ReactRootView createRootView() {
35 | ReactRootView reactRootView = new ReactRootView(getContext());
36 | // If you opted-in for the New Architecture, we enable the Fabric Renderer.
37 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
38 | return reactRootView;
39 | }
40 |
41 | @Override
42 | protected boolean isConcurrentRootEnabled() {
43 | // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
44 | // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
45 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/packages/proton-link/eslint.config.ts:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import tseslint from 'typescript-eslint'
4 | import {defineConfig, globalIgnores} from 'eslint/config'
5 | import prettier from 'eslint-plugin-prettier/recommended'
6 |
7 | export default defineConfig([
8 | globalIgnores(['lib/*', 'node_modules/**/*']),
9 | {
10 | files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
11 | plugins: {js},
12 | extends: ['js/recommended'],
13 | languageOptions: {
14 | globals: {...globals.browser, ...globals.node, NodeJS: true},
15 | parserOptions: {
16 | tsconfigRootDir: __dirname,
17 | },
18 | },
19 | },
20 | tseslint.configs.recommended,
21 | prettier,
22 | {
23 | rules: {
24 | 'prettier/prettier': 'warn',
25 | 'no-console': 'warn',
26 |
27 | 'sort-imports': [
28 | 'warn',
29 | {
30 | ignoreCase: true,
31 | ignoreDeclarationSort: true,
32 | },
33 | ],
34 | '@typescript-eslint/explicit-module-boundary-types': 'off',
35 | '@typescript-eslint/no-explicit-any': 'off',
36 | '@typescript-eslint/no-namespace': 'off',
37 | '@typescript-eslint/no-non-null-assertion': 'off',
38 | '@typescript-eslint/no-empty-function': 'off',
39 | 'no-inner-declarations': 'off',
40 | 'no-unused-vars': [
41 | 'warn',
42 | {
43 | argsIgnorePattern: '^_',
44 | },
45 | ],
46 | '@typescript-eslint/no-unused-vars': [
47 | 'warn',
48 | {
49 | argsIgnorePattern: '^_',
50 | },
51 | ],
52 | },
53 | },
54 | ])
55 |
--------------------------------------------------------------------------------
/examples/react-native/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "31.0.0"
6 | minSdkVersion = 21
7 | compileSdkVersion = 31
8 | targetSdkVersion = 31
9 |
10 | if (System.properties['os.arch'] == "aarch64") {
11 | // For M1 Users we need to use the NDK 24 which added support for aarch64
12 | ndkVersion = "24.0.8215888"
13 | } else {
14 | // Otherwise we default to the side-by-side NDK version from AGP.
15 | ndkVersion = "21.4.7075529"
16 | }
17 | }
18 | repositories {
19 | google()
20 | mavenCentral()
21 | }
22 | dependencies {
23 | classpath("com.android.tools.build:gradle:7.2.1")
24 | classpath("com.facebook.react:react-native-gradle-plugin")
25 | classpath("de.undercouch:gradle-download-task:5.0.1")
26 | // NOTE: Do not place your application dependencies here; they belong
27 | // in the individual module build.gradle files
28 | }
29 | }
30 |
31 | allprojects {
32 | repositories {
33 | maven {
34 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
35 | url("$rootDir/../node_modules/react-native/android")
36 | }
37 | maven {
38 | // Android JSC is installed from npm
39 | url("$rootDir/../node_modules/jsc-android/dist")
40 | }
41 | mavenCentral {
42 | // We don't want to fetch react-native from Maven Central as there are
43 | // older versions over there.
44 | content {
45 | excludeGroup "com.facebook.react"
46 | }
47 | }
48 | google()
49 | maven { url 'https://www.jitpack.io' }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/examples/react/src/store/slices/user.slice.ts:
--------------------------------------------------------------------------------
1 | import type { RpcInterfaces } from '@proton/js';
2 | import { createSlice, type PayloadAction } from '@reduxjs/toolkit'
3 | import type { RootState } from '../store';
4 |
5 | // Define a type for the slice state
6 | interface UserState {
7 | actor: string;
8 | permission: string;
9 | accountData?: RpcInterfaces.UserInfo;
10 | }
11 |
12 | // Define the initial state using that type
13 | const initialState: UserState = {
14 | actor: '',
15 | permission: '',
16 | }
17 |
18 | export const userSlice = createSlice({
19 | name: 'user',
20 | // `createSlice` will infer the state type from the `initialState` argument
21 | initialState,
22 | reducers: {
23 | setUser: (state, action: PayloadAction) => {
24 |
25 | state.actor = action.payload.actor;
26 | state.permission = action.payload.permission;
27 | state.accountData = action.payload.accountData ?? undefined
28 | console.log('setUser', state);
29 | },
30 | clearUser: (state) => {
31 | userSlice.caseReducers.setUser(state, { type: 'setUser', payload: { actor: '', permission: '' }})
32 | }
33 | }
34 | })
35 |
36 | export const { setUser, clearUser } = userSlice.actions
37 |
38 | export const selectUser = (state: RootState) => state.user
39 |
40 | // Other code such as selectors can use the imported `RootState` type
41 | export const selectUserAvatar = ({ user }: RootState) => {
42 |
43 | const avatar = user.accountData && user.accountData.avatar
44 |
45 | if (avatar) {
46 | if (avatar.indexOf('/9j/') !== -1) {
47 | return `data:image/jpeg;base64,${avatar}`
48 | } else if (avatar.indexOf('iVBORw0KGgo') !== -1) {
49 | return `data:image/png;base64,${avatar}`
50 | }
51 | }
52 |
53 | return 'https://explorer.xprnetwork.org/img/proton_avatar.png'
54 | }
55 |
56 | export default userSlice.reducer
--------------------------------------------------------------------------------
/examples/react-native/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.125.0
29 |
30 | # Use this property to specify which architecture you want to build.
31 | # You can also override it from the CLI using
32 | # ./gradlew -PreactNativeArchitectures=x86_64
33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
34 |
35 | # Use this property to enable support to the new architecture.
36 | # This will allow you to use TurboModules and the Fabric render in
37 | # your application. You should enable this flag either if you want
38 | # to write custom TurboModules/Fabric components OR use libraries that
39 | # are providing them.
40 | newArchEnabled=false
41 |
--------------------------------------------------------------------------------
/packages/proton-signing-request/test/misc.ts:
--------------------------------------------------------------------------------
1 | import {strict as assert} from 'assert'
2 | import 'mocha'
3 | import {ChainId, ChainIdVariant, ChainName, RequestFlags} from '../src'
4 |
5 | describe('misc', function () {
6 | it('should create chain id', function () {
7 | const id = ChainId.from(1)
8 | assert.equal(
9 | id.equals('aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906'),
10 | true
11 | )
12 | assert.equal(id.chainVariant.chainId.chainName, ChainName.EOS)
13 | const id2 = ChainId.from('beefbeef06b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906')
14 | assert.equal(id2.chainName, ChainName.UNKNOWN)
15 | assert.equal(id2.chainVariant.variantName, 'chain_id')
16 | assert.equal(id2.chainVariant.chainId.equals(id2), true)
17 | assert.throws(() => {
18 | ChainId.from(99)
19 | })
20 | assert.throws(() => {
21 | ChainIdVariant.from(['chain_alias', 0]).chainId
22 | })
23 | })
24 | it('should set request flags', function () {
25 | const flags = RequestFlags.from(0)
26 | assert.equal(flags.background, false)
27 | assert.equal(flags.broadcast, false)
28 | flags.background = true
29 | assert.equal(flags.background, true)
30 | assert.equal(flags.broadcast, false)
31 | assert.equal(Number(flags), 2)
32 | flags.broadcast = true
33 | assert.equal(flags.background, true)
34 | assert.equal(flags.broadcast, true)
35 | assert.equal(Number(flags), 3)
36 | flags.background = false
37 | assert.equal(flags.background, false)
38 | assert.equal(flags.broadcast, true)
39 | assert.equal(Number(flags), 1)
40 | flags.broadcast = false
41 | assert.equal(flags.background, false)
42 | assert.equal(flags.broadcast, false)
43 | assert.equal(Number(flags), 0)
44 | })
45 | })
46 |
--------------------------------------------------------------------------------
/packages/proton-link/examples/transact/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Proton Link - Transact
7 |
8 |
9 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/examples/react-native/ios/example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | example
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleURLTypes
24 |
25 |
26 | CFBundleURLSchemes
27 |
28 | example
29 |
30 |
31 |
32 | CFBundleVersion
33 | 1
34 | LSRequiresIPhoneOS
35 |
36 | NSAppTransportSecurity
37 |
38 | NSExceptionDomains
39 |
40 | localhost
41 |
42 | NSExceptionAllowsInsecureHTTPLoads
43 |
44 |
45 |
46 |
47 | NSLocationWhenInUseUsageDescription
48 |
49 | UILaunchStoryboardName
50 | LaunchScreen
51 | UIRequiredDeviceCapabilities
52 |
53 | armv7
54 |
55 | UISupportedInterfaceOrientations
56 |
57 | UIInterfaceOrientationPortrait
58 | UIInterfaceOrientationLandscapeLeft
59 | UIInterfaceOrientationLandscapeRight
60 |
61 | UIViewControllerBasedStatusBarAppearance
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/examples/svelte/src/lib/components/Avatar.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | {#if $actor === ''}
12 |
login(false)}
14 | class="cursor-pointer whitespace-nowrap bg-purple-100 border border-transparent rounded-md py-2 px-4 inline-flex items-center justify-center text-base font-medium text-purple-600 hover:bg-purple-200"
15 | >
16 | Login
17 |
18 | {:else}
19 |
20 |
49 |
50 | {/if}
51 |
52 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/src/main/java/com/example/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java:
--------------------------------------------------------------------------------
1 | package com.example.newarchitecture.modules;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.react.ReactPackage;
5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.soloader.SoLoader;
8 | import java.util.List;
9 |
10 | /**
11 | * Class responsible to load the TurboModules. This class has native methods and needs a
12 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
13 | * folder for you).
14 | *
15 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
16 | * `newArchEnabled` property). Is ignored otherwise.
17 | */
18 | public class MainApplicationTurboModuleManagerDelegate
19 | extends ReactPackageTurboModuleManagerDelegate {
20 |
21 | private static volatile boolean sIsSoLibraryLoaded;
22 |
23 | protected MainApplicationTurboModuleManagerDelegate(
24 | ReactApplicationContext reactApplicationContext, List packages) {
25 | super(reactApplicationContext, packages);
26 | }
27 |
28 | protected native HybridData initHybrid();
29 |
30 | native boolean canCreateTurboModule(String moduleName);
31 |
32 | public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
33 | protected MainApplicationTurboModuleManagerDelegate build(
34 | ReactApplicationContext context, List packages) {
35 | return new MainApplicationTurboModuleManagerDelegate(context, packages);
36 | }
37 | }
38 |
39 | @Override
40 | protected synchronized void maybeLoadOtherSoLibraries() {
41 | if (!sIsSoLibraryLoaded) {
42 | // If you change the name of your application .so file in the Android.mk file,
43 | // make sure you update the name here as well.
44 | SoLoader.loadLibrary("example_appmodules");
45 | sIsSoLibraryLoaded = true;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/examples/svelte/src/lib/components/Transfer.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
36 |
37 |
38 |
39 |
40 |
41 |
49 |
50 |
51 |
52 |
53 |
transfer({ to, amount })}
56 | >
57 | Transfer
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/packages/proton-web-sdk/Makefile:
--------------------------------------------------------------------------------
1 | SRC_FILES := $(shell find src -name '*.ts')
2 |
3 | lib: ${SRC_FILES} package.json tsconfig.json node_modules rollup.config.js
4 | @./node_modules/.bin/rollup -c
5 |
6 | .PHONY: test
7 | test: node_modules
8 | @TS_NODE_PROJECT='./test/tsconfig.json' ./node_modules/.bin/mocha -u tdd -r ts-node/register --extension ts test/*.ts --grep '$(grep)'
9 |
10 | .PHONY: coverage
11 | coverage: node_modules
12 | @TS_NODE_PROJECT='./test/tsconfig.json' ./node_modules/.bin/nyc --reporter=html ./node_modules/.bin/mocha -u tdd -r ts-node/register --extension ts test/*.ts -R nyan && open coverage/index.html
13 |
14 | .PHONY: lint
15 | lint: node_modules
16 | @./node_modules/.bin/eslint src --ext .ts --fix
17 |
18 | .PHONY: ci-test
19 | ci-test: node_modules
20 | @TS_NODE_PROJECT='./test/tsconfig.json' ./node_modules/.bin/nyc --reporter=text ./node_modules/.bin/mocha -u tdd -r ts-node/register --extension ts test/*.ts -R list
21 |
22 | .PHONY: ci-lint
23 | ci-lint: node_modules
24 | @./node_modules/.bin/eslint src --ext .ts --max-warnings 0 --format unix && echo "Ok"
25 |
26 | docs: $(SRC_FILES) node_modules
27 | ./node_modules/.bin/typedoc \
28 | --excludeInternal \
29 | --excludePrivate --excludeProtected \
30 | --name "Proton Link" --includeVersion --readme none \
31 | --out docs \
32 | src/index-module.ts
33 |
34 | .PHONY: deploy-site
35 | deploy-site: docs
36 | cp -r ./examples ./docs/examples/
37 | ./node_modules/.bin/gh-pages -d docs
38 |
39 | node_modules:
40 | yarn install --non-interactive --frozen-lockfile --ignore-scripts
41 |
42 | .PHONY: publish
43 | publish: | distclean node_modules
44 | @git diff-index --quiet HEAD || (echo "Uncommitted changes, please commit first" && exit 1)
45 | @git fetch origin && git diff origin/master --quiet || (echo "Changes not pushed to origin, please push first" && exit 1)
46 | @yarn config set version-tag-prefix "" && yarn config set version-git-message "Version %s"
47 | @yarn publish && git push && git push --tags
48 |
49 | .PHONY: clean
50 | clean:
51 | rm -rf lib/ coverage/ docs/
52 |
53 | .PHONY: distclean
54 | distclean: clean
55 | rm -rf node_modules/
56 |
--------------------------------------------------------------------------------
/packages/proton-link/Makefile:
--------------------------------------------------------------------------------
1 | SRC_FILES := $(shell find src -name '*.ts')
2 |
3 | lib: ${SRC_FILES} package.json tsconfig.json node_modules rollup.config.js
4 | @./node_modules/.bin/rollup -c && touch lib
5 |
6 | .PHONY: test
7 | test: node_modules
8 | @TS_NODE_PROJECT='./test/tsconfig.json' ./node_modules/.bin/mocha -u tdd -r ts-node/register --extension ts test/*.ts --grep '$(grep)'
9 |
10 | .PHONY: coverage
11 | coverage: node_modules
12 | @TS_NODE_PROJECT='./test/tsconfig.json' ./node_modules/.bin/nyc --reporter=html ./node_modules/.bin/mocha -u tdd -r ts-node/register --extension ts test/*.ts -R nyan && open coverage/index.html
13 |
14 | .PHONY: lint
15 | lint: node_modules
16 | @./node_modules/.bin/eslint src --ext .ts --fix
17 |
18 | .PHONY: ci-test
19 | ci-test: node_modules
20 | @TS_NODE_PROJECT='./test/tsconfig.json' ./node_modules/.bin/nyc --reporter=text ./node_modules/.bin/mocha -u tdd -r ts-node/register --extension ts test/*.ts -R list
21 |
22 | .PHONY: ci-lint
23 | ci-lint: node_modules
24 | @./node_modules/.bin/eslint src --ext .ts --max-warnings 0 --format unix && echo "Ok"
25 |
26 | docs: $(SRC_FILES) node_modules
27 | ./node_modules/.bin/typedoc \
28 | --excludeInternal \
29 | --excludePrivate --excludeProtected \
30 | --name "Proton Link" --includeVersion --readme none \
31 | --out docs \
32 | src/index-module.ts
33 |
34 | .PHONY: deploy-site
35 | deploy-site: docs
36 | cp -r ./examples ./docs/examples/
37 | ./node_modules/.bin/gh-pages -d docs
38 |
39 | node_modules:
40 | yarn install --non-interactive --frozen-lockfile --ignore-scripts
41 |
42 | .PHONY: publish
43 | publish: | distclean node_modules
44 | @git diff-index --quiet HEAD || (echo "Uncommitted changes, please commit first" && exit 1)
45 | @git fetch origin && git diff origin/master --quiet || (echo "Changes not pushed to origin, please push first" && exit 1)
46 | @yarn config set version-tag-prefix "" && yarn config set version-git-message "Version %s"
47 | @yarn publish && git push && git push --tags
48 |
49 | .PHONY: clean
50 | clean:
51 | rm -rf lib/ coverage/ docs/
52 |
53 | .PHONY: distclean
54 | distclean: clean
55 | rm -rf node_modules/
56 |
--------------------------------------------------------------------------------
/examples/react-native/webSdk.ts:
--------------------------------------------------------------------------------
1 | import ProtonRNSDK, {ProtonLink} from '@proton/react-native-sdk';
2 | import type {LinkSession} from '@proton/react-native-sdk';
3 |
4 | class ProtonSDK {
5 | chainId;
6 | endpoints;
7 | requestAccount;
8 | session: LinkSession | null | undefined;
9 | link: ProtonLink | null;
10 |
11 | constructor() {
12 | this.chainId =
13 | '71ee83bcf52142d61019d95f9cc5427ba6a0d7ff8accd9e2088ae2abeaf3d3dd';
14 | this.endpoints = ['https://testnet.protonchain.com']; // Multiple for fault tolerance
15 | this.requestAccount = 'taskly'; // optional
16 | this.session = null;
17 | this.link = null;
18 | }
19 |
20 | login = async () => {
21 | const {session, link} = await ProtonRNSDK({
22 | linkOptions: {
23 | chainId: this.chainId,
24 | endpoints: this.endpoints,
25 | },
26 | transportOptions: {
27 | requestAccount: this.requestAccount,
28 | getReturnUrl: () => 'example://main',
29 | },
30 | });
31 |
32 | this.link = link;
33 | this.session = session;
34 |
35 | console.log('Auth: ', this.session?.auth);
36 | };
37 |
38 | transfer = async () => {
39 | if (!this.session) {
40 | return;
41 | }
42 |
43 | return this.session.transact(
44 | {
45 | transaction: {
46 | actions: [
47 | {
48 | account: 'eosio.token',
49 | name: 'transfer',
50 | authorization: [this.session.auth],
51 | data: {
52 | from: this.session.auth.actor,
53 | to: 'token.burn',
54 | quantity: '0.0001 XPR',
55 | memo: '',
56 | },
57 | },
58 | ],
59 | } as never,
60 | },
61 | {
62 | broadcast: true,
63 | },
64 | );
65 | };
66 |
67 | logout = async () => {
68 | if (this.link && this.session) {
69 | await this.link.removeSession(this.requestAccount, this.session.auth);
70 |
71 | this.link = null;
72 | this.session = undefined;
73 | }
74 |
75 | };
76 | }
77 |
78 | export const sdk = new ProtonSDK();
79 |
--------------------------------------------------------------------------------
/examples/angular/src/app/components/avatar/avatar.component.html:
--------------------------------------------------------------------------------
1 | @if(actor$ | async; as actor) {
2 |
4 |
5 |
7 |
![Profile Photo]()
11 |
12 |
14 | {{ actor }}
15 |
16 |
17 |
32 |
33 |
34 |
35 | } @else {
36 |
39 | Login
40 |
41 |
42 | }
--------------------------------------------------------------------------------
/packages/proton-react-native-sdk/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@proton/react-native-sdk",
3 | "author": "Metallicus",
4 | "module": "lib/react-native-sdk.m.js",
5 | "unpkg": "lib/react-native-sdk.bundle.js",
6 | "types": "lib/types/index.d.ts",
7 | "source": "src/index.ts",
8 | "version": "4.4.1",
9 | "license": "MIT",
10 | "main": "lib/react-native-sdk.js",
11 | "typings": "lib/types/index.d.ts",
12 | "type": "module",
13 | "files": [
14 | "lib",
15 | "src"
16 | ],
17 | "engines": {
18 | "node": ">=10"
19 | },
20 | "publishConfig": {
21 | "access": "public"
22 | },
23 | "scripts": {
24 | "watch": "rollup -c -w",
25 | "prepare": "make",
26 | "build": "make",
27 | "lint": "make lint"
28 | },
29 | "dependencies": {
30 | "@proton/js": "^28.1.2",
31 | "@proton/link": "workspace:^",
32 | "@proton/signing-request": "workspace:^",
33 | "@react-native-async-storage/async-storage": "^1.24.0",
34 | "buffer": "^6.0.3",
35 | "react-native": "^0.70.0",
36 | "react-native-get-random-values": "^1.11.0",
37 | "text-encoding-shim": "^1.0.5"
38 | },
39 | "peerDependencies": {
40 | "react": "^18.0.0",
41 | "@react-native-async-storage/async-storage": "^1.24.0",
42 | "react-native-get-random-values": "^1.11.0"
43 | },
44 | "gitHead": "e15e7e40cc610b4a7ceeaee75909ff6389d8f1e5",
45 | "devDependencies": {
46 |
47 | "@eslint/js": "^9.39.1",
48 | "@rollup/plugin-commonjs": "^28.0.3",
49 | "@rollup/plugin-json": "^6.1.0",
50 | "@rollup/plugin-node-resolve": "^16.0.1",
51 | "@rollup/plugin-replace": "^6.0.2",
52 | "@rollup/plugin-terser": "^0.4.4",
53 | "@rollup/plugin-typescript": "^12.1.2",
54 | "@types/node": "^16.4.0",
55 | "@types/react-native": "^0.70.0",
56 | "eslint": "^9.39.1",
57 | "eslint-config-prettier": "^10.1.8",
58 | "eslint-plugin-prettier": "^5.5.4",
59 | "globals": "^16.5.0",
60 | "jiti": "^2.6.1",
61 | "prettier": "^3.5.3",
62 | "rollup": "^4.40.0",
63 | "rollup-plugin-dts": "^6.2.1",
64 | "ts-node": "^10.0.0",
65 | "tslib": "^2.4.0",
66 | "typescript": "~5.4.0",
67 | "typescript-eslint": "^8.46.4"
68 | }
69 | }
--------------------------------------------------------------------------------
/packages/proton-browser-transport/README.md:
--------------------------------------------------------------------------------
1 | # Proton Link - Browser Transport [](https://www.npmjs.com/package/@proton/browser-transport) 
2 |
3 | A transport library for usage of [Proton Link](https://github.com/protonprotocol/proton-link) within a web browser environment.
4 |
5 | ## Basic usage
6 |
7 | A transport is required for Proton Link to communicate with clients. In most examples we use the browser transport with no configuration, like so:
8 |
9 | ```ts
10 | const transport = new ProtonBrowserTransport()
11 | const link = new ProtonLink({transport})
12 | ```
13 |
14 | Parameters can be passed to the transport during construction as an object, allowing for the following optional changes:
15 |
16 | ```ts
17 | const transport = new ProtonBrowserTransport({
18 | /** Whether to display request success and error messages, defaults to true */
19 | requestStatus: true,
20 | /** Local storage prefix, defaults to `proton-link`. */
21 | storagePrefix: 'my-localstorage-prefix',
22 | /**
23 | * Whether to use Greymass Fuel for low resource accounts, defaults to false.
24 | * Note that this service is not available on all networks, and will automatically
25 | * determine based on chain id if it should be enabled or not.
26 | */
27 | disableGreymassFuel: false,
28 | /** Referral account to use for Greymass Fuel. */
29 | fuelReferrer: 'teamgreymass',
30 | })
31 | const link = new ProtonLink({transport})
32 | ```
33 |
34 | ## Developing
35 |
36 | You need [Make](https://www.gnu.org/software/make/), [node.js](https://nodejs.org/en/) and [yarn](https://classic.yarnpkg.com/en/docs/install) installed.
37 |
38 | Clone the repository and run `make` to checkout all dependencies and build the project. See the [Makefile](./Makefile) for other useful targets. Before submitting a pull request make sure to run `make lint`.
39 |
40 | ## License
41 |
42 | [MIT](./LICENSE.md)
43 |
44 | ---
45 |
46 | Made with ☕️ & ❤️ by [Greymass](https://greymass.com), if you find this useful please consider [supporting us](https://greymass.com/support-us).
47 |
--------------------------------------------------------------------------------
/examples/react-native/ios/exampleTests/exampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface exampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation exampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(
38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
39 | if (level >= RCTLogLevelError) {
40 | redboxError = message;
41 | }
42 | });
43 | #endif
44 |
45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
48 |
49 | foundElement = [self findSubviewInView:vc.view
50 | matching:^BOOL(UIView *view) {
51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
52 | return YES;
53 | }
54 | return NO;
55 | }];
56 | }
57 |
58 | #ifdef DEBUG
59 | RCTSetLogFunction(RCTDefaultLogFunction);
60 | #endif
61 |
62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/packages/proton-web-sdk/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@proton/web-sdk",
3 | "version": "4.4.1",
4 | "license": "MIT",
5 | "author": "metallicus",
6 | "publishConfig": {
7 | "access": "public"
8 | },
9 | "type": "module",
10 | "main": "lib/proton-web-sdk.js",
11 | "module": "lib/proton-web-sdk.m.js",
12 | "unpkg": "lib/proton-web-sdk.bundle.js",
13 | "types": "lib/types/proton-web-sdk.d.ts",
14 | "typings": "lib/types/index.d.ts",
15 | "source": "src/index.ts",
16 | "files": [
17 | "lib",
18 | "src"
19 | ],
20 | "engines": {
21 | "node": ">=10"
22 | },
23 | "scripts": {
24 | "watch": "rollup -c -w",
25 | "build": "make",
26 | "lint": "make lint",
27 | "prepare": "make",
28 | "size": "size-limit",
29 | "analyze": "size-limit --why"
30 | },
31 | "dependencies": {
32 | "@greymass/eosio": "^0.6.1",
33 | "@proton/browser-transport": "workspace:^",
34 | "@proton/js": "^28.1.2",
35 | "@proton/link": "workspace:^"
36 | },
37 | "gitHead": "d81cd76c8aacc2538243e24d0801b3eae4b8dba2",
38 | "devDependencies": {
39 | "@eslint/css": "^0.14.1",
40 | "@eslint/js": "^9.39.1",
41 | "@eslint/json": "^0.14.0",
42 | "@rollup/plugin-commonjs": "^28.0.3",
43 | "@rollup/plugin-json": "^6.1.0",
44 | "@rollup/plugin-node-resolve": "^16.0.1",
45 | "@rollup/plugin-replace": "^6.0.2",
46 | "@rollup/plugin-terser": "^0.4.4",
47 | "@rollup/plugin-typescript": "^12.1.2",
48 | "@tsconfig/svelte": "^5.0.4",
49 | "@types/node": "^16.4.0",
50 | "core-js": "^3.42.0",
51 | "eslint": "^9.39.1",
52 | "eslint-config-prettier": "^10.1.8",
53 | "eslint-plugin-prettier": "^5.5.4",
54 | "eslint-plugin-svelte": "^3.13.0",
55 | "globals": "^16.5.0",
56 | "jiti": "^2.6.1",
57 | "postcss": "^8.5.3",
58 | "prettier": "^3.5.3",
59 | "prettier-plugin-svelte": "^3.4.0",
60 | "rollup": "^4.40.0",
61 | "rollup-plugin-dts": "^6.2.1",
62 | "rollup-plugin-svelte": "^7.2.0",
63 | "sass": "^1.89.0",
64 | "svelte": "^5.41.0",
65 | "svelte-check": "^4.3.3",
66 | "svelte-eslint-parser": "^1.4.0",
67 | "svelte-preprocess": "^6.0.3",
68 | "ts-node": "^10.0.0",
69 | "tslib": "^2.4.0",
70 | "typescript": "~5.4.0",
71 | "typescript-eslint": "^8.46.4"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/packages/proton-browser-transport/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@proton/browser-transport",
3 | "version": "4.4.1",
4 | "description": "Vanilla JS browser transport for Proton Link",
5 | "homepage": "https://github.com/protonprotocol/proton-browser-transport",
6 | "license": "BSD-3-Clause",
7 | "type": "module",
8 | "main": "lib/proton-browser-transport.js",
9 | "module": "lib/proton-browser-transport.m.js",
10 | "unpkg": "lib/proton-browser-transport.bundle.js",
11 | "types": "lib/types/proton-browser-transport.d.ts",
12 | "typings": "lib/types/index.d.ts",
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "scripts": {
17 | "watch": "rollup -c -w",
18 | "prepare": "make",
19 | "build": "make",
20 | "lint": "make lint"
21 | },
22 | "files": [
23 | "lib",
24 | "src"
25 | ],
26 | "dependencies": {
27 | "@proton/link": "workspace:^"
28 | },
29 | "peerDependencies": {
30 | "@proton/link": "workspace:^"
31 | },
32 | "devDependencies": {
33 | "@eslint/css": "^0.14.1",
34 | "@eslint/js": "^9.39.1",
35 | "@eslint/json": "^0.14.0",
36 | "@rollup/plugin-commonjs": "^28.0.3",
37 | "@rollup/plugin-json": "^6.1.0",
38 | "@rollup/plugin-node-resolve": "^16.0.1",
39 | "@rollup/plugin-replace": "^6.0.2",
40 | "@rollup/plugin-terser": "^0.4.4",
41 | "@rollup/plugin-typescript": "^12.1.2",
42 | "@tsconfig/svelte": "^5.0.4",
43 | "@types/node": "^16.4.0",
44 | "@types/ws": "^7.2.2",
45 | "core-js": "^3.42.0",
46 | "eslint": "^9.39.1",
47 | "eslint-config-prettier": "^10.1.8",
48 | "eslint-plugin-prettier": "^5.5.4",
49 | "eslint-plugin-svelte": "^3.13.0",
50 | "globals": "^16.5.0",
51 | "jiti": "^2.6.1",
52 | "postcss": "^8.5.3",
53 | "prettier": "^3.5.3",
54 | "prettier-plugin-svelte": "^3.4.0",
55 | "rollup": "^4.40.0",
56 | "rollup-plugin-dts": "^6.2.1",
57 | "rollup-plugin-svelte": "^7.2.0",
58 | "sass": "^1.89.0",
59 | "svelte": "^5.41.0",
60 | "svelte-check": "^4.3.3",
61 | "svelte-eslint-parser": "^1.4.0",
62 | "svelte-preprocess": "^6.0.3",
63 | "ts-node": "^10.0.0",
64 | "tslib": "^2.4.0",
65 | "typescript": "~5.4.0",
66 | "typescript-eslint": "^8.46.4"
67 | },
68 | "gitHead": "d81cd76c8aacc2538243e24d0801b3eae4b8dba2"
69 | }
70 |
--------------------------------------------------------------------------------
/packages/proton-web-sdk/eslint.config.ts:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import tseslint from 'typescript-eslint'
4 | import css from '@eslint/css'
5 | import {defineConfig, globalIgnores} from 'eslint/config'
6 | import svelte from 'eslint-plugin-svelte'
7 | import svelteparser from 'svelte-eslint-parser'
8 | import prettier from 'eslint-plugin-prettier/recommended'
9 |
10 | export default defineConfig([
11 | globalIgnores(['lib/*', 'node_modules/**/*']),
12 | {
13 | files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
14 | plugins: {js},
15 | extends: ['js/recommended'],
16 | languageOptions: {
17 | globals: {...globals.browser, ...globals.node, NodeJS: true},
18 | parserOptions: {
19 | extraFileExtensions: ['.svelte'],
20 | tsconfigRootDir: __dirname,
21 | },
22 | },
23 | },
24 | tseslint.configs.recommended,
25 | svelte.configs.recommended,
26 | prettier,
27 | svelte.configs.prettier,
28 | {
29 | files: ['**/*.svelte', '**/*.svelte.ts'],
30 | languageOptions: {
31 | parser: svelteparser,
32 | parserOptions: {
33 | parser: tseslint.parser,
34 | extraFileExtensions: ['.svelte'],
35 | },
36 | },
37 | },
38 | {
39 | rules: {
40 | 'prettier/prettier': 'warn',
41 | 'no-console': 'warn',
42 |
43 | 'sort-imports': [
44 | 'warn',
45 | {
46 | ignoreCase: true,
47 | ignoreDeclarationSort: true,
48 | },
49 | ],
50 | '@typescript-eslint/explicit-module-boundary-types': 'off',
51 | '@typescript-eslint/no-explicit-any': 'off',
52 | '@typescript-eslint/no-namespace': 'off',
53 | '@typescript-eslint/no-non-null-assertion': 'off',
54 | '@typescript-eslint/no-empty-function': 'off',
55 | 'no-inner-declarations': 'off',
56 | 'no-unused-vars': [
57 | 'warn',
58 | {
59 | argsIgnorePattern: '^_',
60 | },
61 | ],
62 | '@typescript-eslint/no-unused-vars': [
63 | 'warn',
64 | {
65 | argsIgnorePattern: '^_',
66 | },
67 | ],
68 | },
69 | },
70 | {files: ['**/*.css'], plugins: {css}, language: 'css/css', extends: ['css/recommended']},
71 |
72 | // {files: ['**/*.json'], plugins: {json}, language: 'json/json', extends: ['json/recommended']},
73 | ])
74 |
--------------------------------------------------------------------------------
/packages/proton-browser-transport/eslint.config.ts:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import tseslint from 'typescript-eslint'
4 | import css from '@eslint/css'
5 | import {defineConfig, globalIgnores} from 'eslint/config'
6 | import svelte from 'eslint-plugin-svelte'
7 | import svelteparser from 'svelte-eslint-parser'
8 | import prettier from 'eslint-plugin-prettier/recommended'
9 |
10 | export default defineConfig([
11 | globalIgnores(['lib/*', 'node_modules/**/*']),
12 | {
13 | files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
14 | plugins: {js},
15 | extends: ['js/recommended'],
16 | languageOptions: {
17 | globals: {...globals.browser, ...globals.node, NodeJS: true},
18 | parserOptions: {
19 | extraFileExtensions: ['.svelte'],
20 | tsconfigRootDir: __dirname,
21 | },
22 | },
23 | },
24 | tseslint.configs.recommended,
25 | svelte.configs.recommended,
26 | prettier,
27 | svelte.configs.prettier,
28 | {
29 | files: ['**/*.svelte', '**/*.svelte.ts'],
30 | languageOptions: {
31 | parser: svelteparser,
32 | parserOptions: {
33 | parser: tseslint.parser,
34 | extraFileExtensions: ['.svelte'],
35 | },
36 | },
37 | },
38 | {
39 | rules: {
40 | 'prettier/prettier': 'warn',
41 | 'no-console': 'warn',
42 |
43 | 'sort-imports': [
44 | 'warn',
45 | {
46 | ignoreCase: true,
47 | ignoreDeclarationSort: true,
48 | },
49 | ],
50 | '@typescript-eslint/explicit-module-boundary-types': 'off',
51 | '@typescript-eslint/no-explicit-any': 'off',
52 | '@typescript-eslint/no-namespace': 'off',
53 | '@typescript-eslint/no-non-null-assertion': 'off',
54 | '@typescript-eslint/no-empty-function': 'off',
55 | 'no-inner-declarations': 'off',
56 | 'no-unused-vars': [
57 | 'warn',
58 | {
59 | argsIgnorePattern: '^_',
60 | },
61 | ],
62 | '@typescript-eslint/no-unused-vars': [
63 | 'warn',
64 | {
65 | argsIgnorePattern: '^_',
66 | },
67 | ],
68 | },
69 | },
70 | {files: ['**/*.css'], plugins: {css}, language: 'css/css', extends: ['css/recommended']},
71 |
72 | // {files: ['**/*.json'], plugins: {json}, language: 'json/json', extends: ['json/recommended']},
73 | ])
74 |
--------------------------------------------------------------------------------
/examples/angular/src/app/services/user/user.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { RpcInterfaces } from '@proton/js';
3 |
4 | import { WebSdkService } from '../web-sdk/web-sdk.service';
5 | import { from, map, of, ReplaySubject, shareReplay, switchMap } from 'rxjs';
6 |
7 | @Injectable({
8 | providedIn: 'root',
9 | })
10 | export class UserService {
11 | readonly actor$ = new ReplaySubject(1);
12 | readonly permission$ = new ReplaySubject(1);
13 |
14 | readonly accountData$ = this.actor$.pipe(
15 | switchMap((actor) => {
16 | if (actor) {
17 | return from(this.sdk.getProtonAvatar(actor));
18 | }
19 | return of(undefined);
20 | }),
21 | shareReplay({
22 | bufferSize: 1,
23 | refCount: false,
24 | })
25 | );
26 |
27 | readonly avatar$ = this.accountData$.pipe(
28 | map((data) => this.getAvatar(data)),
29 | shareReplay({
30 | bufferSize: 1,
31 | refCount: false,
32 | })
33 | );
34 |
35 | private sdk = inject(WebSdkService);
36 |
37 | constructor() {
38 | this.login(true);
39 |
40 | }
41 |
42 | async login(reconnect: boolean = false) {
43 | this.clear();
44 |
45 | if (reconnect) {
46 | await this.sdk.reconnect();
47 | } else {
48 | await this.sdk.login();
49 | }
50 |
51 | if (this.sdk.session?.auth) {
52 | this.actor$.next(this.sdk.session.auth.actor.toString());
53 | this.permission$.next(this.sdk.session.auth.permission.toString());
54 | }
55 | }
56 |
57 | async logout() {
58 | await this.sdk.logout();
59 | this.clear();
60 | }
61 |
62 | async transfer(to: string, amount: string) {
63 | await this.sdk.transfer({
64 | to: to,
65 | amount: amount,
66 | });
67 | }
68 |
69 | private getAvatar(data?: RpcInterfaces.UserInfo): string {
70 | const avatar = data?.avatar;
71 |
72 | if (avatar) {
73 | if (avatar.indexOf('/9j/') !== -1) {
74 | return `data:image/jpeg;base64,${avatar}`;
75 | } else if (avatar.indexOf('iVBORw0KGgo') !== -1) {
76 | return `data:image/png;base64,${avatar}`;
77 | }
78 | }
79 |
80 | return 'https://explorer.xprnetwork.org/img/proton_avatar.png';
81 | }
82 |
83 | private clear() {
84 | this.actor$.next('');
85 | this.permission$.next('');
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/examples/angular/src/app/components/transfer/transfer.component.html:
--------------------------------------------------------------------------------
1 |
2 | @let actor = actor$ | async;
3 |
4 |
5 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
29 |
30 |
31 |
32 |
34 |
35 |
41 |
42 |
43 |
44 |
45 |
51 |
52 |
--------------------------------------------------------------------------------
/packages/proton-link/src/link-transport.ts:
--------------------------------------------------------------------------------
1 | import type {Bytes} from '@greymass/eosio'
2 | import type {SigningRequest} from '@proton/signing-request'
3 |
4 | import type {TransactResult} from './link'
5 | import type {LinkSession} from './link-session'
6 | import type {LinkStorage} from './link-storage'
7 |
8 | /**
9 | * Protocol link transports need to implement.
10 | *
11 | * A transport is responsible for getting the request to the
12 | * user, e.g. by opening request URIs or displaying QR codes.
13 | */
14 | export interface LinkTransport {
15 | /**
16 | * Present a signing request to the user.
17 | * @param request The signing request.
18 | * @param cancel Can be called to abort the request.
19 | */
20 | onRequest(request: SigningRequest, cancel: (reason: string | Error) => void): void
21 | /** Called if the request was successful. */
22 | onSuccess?(request: SigningRequest, result: TransactResult): void
23 | /** Called if the request failed. */
24 | onFailure?(request: SigningRequest, error: Error): void
25 | /**
26 | * Called when a session request is initiated.
27 | * @param session Session where the request originated.
28 | * @param request Signing request that will be sent over the session.
29 | */
30 | onSessionRequest?(
31 | session: LinkSession,
32 | request: SigningRequest,
33 | cancel: (reason: string | Error) => void
34 | ): void
35 | /** Can be implemented if transport provides a storage as well. */
36 | storage?: LinkStorage
37 | /** Can be implemented to modify request just after it has been created. */
38 | prepare?(request: SigningRequest, session?: LinkSession): Promise
39 | /** Called immediately when the transaction starts */
40 | showLoading?(): void
41 | /** User agent reported to the signer. */
42 | userAgent?(): string
43 | /** Send session request payload, optional. Can return false to indicate it has to be sent over the socket. */
44 | sendSessionPayload?(payload: Bytes, session: LinkSession): boolean
45 | /**
46 | * Can be implemented to recover from certain errors, if the function returns true the error will
47 | * not bubble up to the caller of .transact or .login and the link will continue waiting for the callback.
48 | */
49 | recoverError?(error: Error, request: SigningRequest): boolean
50 | }
51 |
--------------------------------------------------------------------------------
/packages/proton-react-native-sdk/rollup.config.js:
--------------------------------------------------------------------------------
1 | import {createRequire} from 'module'
2 | import fs from 'fs'
3 | import dts from 'rollup-plugin-dts'
4 | import typescript from '@rollup/plugin-typescript'
5 | import replace from '@rollup/plugin-replace'
6 |
7 | const pkg = createRequire(import.meta.url)('./package.json')
8 | const production = !process.env.ROLLUP_WATCH
9 |
10 | const license = fs.readFileSync('LICENSE').toString('utf-8').trim()
11 | const banner = `
12 | /**
13 | * Proton React Native SDK v${pkg.version}
14 | * ${pkg.homepage}
15 | *
16 | * @license
17 | * ${license.replace(/\n/g, '\n * ')}
18 | */
19 | `.trim()
20 |
21 | const replaceVersion = replace({
22 | preventAssignment: true,
23 | __ver: pkg.version,
24 | })
25 |
26 | export default [
27 | {
28 | input: 'src/index.ts',
29 | output: {
30 | banner,
31 | file: pkg.main,
32 | format: 'cjs',
33 | sourcemap: !production,
34 | exports: 'named',
35 | },
36 | plugins: [
37 | replaceVersion,
38 | typescript({
39 | sourceMap: !production,
40 | target: 'es6',
41 | }),
42 | ],
43 | external: Object.keys({...pkg.dependencies, ...pkg.peerDependencies}),
44 | onwarn,
45 | },
46 |
47 | {
48 | input: 'src/index.ts',
49 | output: {
50 | banner,
51 | file: pkg.module,
52 | format: 'esm',
53 | sourcemap: !production,
54 | },
55 | plugins: [
56 | replaceVersion,
57 | typescript({
58 | sourceMap: !production,
59 | target: 'es6',
60 | }),
61 | ],
62 | external: Object.keys({...pkg.dependencies, ...pkg.peerDependencies}),
63 | onwarn,
64 | },
65 |
66 | {
67 | input: 'src/index.ts',
68 | output: {banner, file: pkg.types, format: 'esm'},
69 | onwarn,
70 | plugins: [dts()],
71 | },
72 | ]
73 |
74 | function onwarn(warning, rollupWarn) {
75 | if (warning.code === 'CIRCULAR_DEPENDENCY') {
76 | // unnecessary warning
77 | return
78 | }
79 | if (
80 | warning.code === 'UNUSED_EXTERNAL_IMPORT' &&
81 | warning.source === 'tslib' &&
82 | warning.names[0] === '__read'
83 | ) {
84 | // when using ts with importHelpers: true rollup complains about this
85 | // seems safe to ignore since __read is not actually imported or used anywhere in the resulting bundles
86 | return
87 | }
88 | rollupWarn(warning)
89 | }
90 |
--------------------------------------------------------------------------------
/packages/proton-signing-request/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@proton/signing-request",
3 | "version": "4.4.1",
4 | "description": "Proton Signing Request (ESR / EEP-7) encoder and decoder",
5 | "homepage": "https://github.com/ProtonProtocol/proton-signing-request",
6 | "license": "MIT",
7 | "main": "lib/proton-signing-request.js",
8 | "module": "lib/proton-signing-request.m.js",
9 | "unpkg": "lib/proton-signing-request.bundle.js",
10 | "types": "lib/types/proton-signing-request.d.ts",
11 | "sideEffects": false,
12 | "type": "module",
13 | "files": [
14 | "lib",
15 | "src"
16 | ],
17 | "publishConfig": {
18 | "access": "public"
19 | },
20 | "scripts": {
21 | "watch": "rollup -c -w",
22 | "prepare": "make",
23 | "build": "make",
24 | "lint": "make lint"
25 | },
26 | "dependencies": {
27 | "@greymass/eosio": "^0.6.1"
28 | },
29 | "devDependencies": {
30 | "@eslint/js": "^9.39.1",
31 | "@babel/plugin-transform-class-properties": "^7.27.1",
32 | "@babel/plugin-proposal-decorators": "^7.28.0",
33 | "@babel/preset-env": "^7.28.5",
34 | "@babel/preset-typescript": "^7.28.5",
35 | "@rollup/plugin-babel": "^6.1.0",
36 | "@rollup/plugin-commonjs": "^28.0.3",
37 | "@rollup/plugin-json": "^6.1.0",
38 | "@rollup/plugin-node-resolve": "^16.0.1",
39 | "@rollup/plugin-replace": "^6.0.2",
40 | "@rollup/plugin-terser": "^0.4.4",
41 | "@rollup/plugin-typescript": "^12.1.2",
42 | "@types/bn.js": "^5.1.0",
43 | "@types/mocha": "^9.1.1",
44 | "@types/node": "^16.4.0",
45 | "@typescript-eslint/eslint-plugin": "^8.33.0",
46 | "@typescript-eslint/parser": "^8.33.0",
47 | "core-js": "^3.42.0",
48 | "eslint": "^9.39.1",
49 | "eslint-config-prettier": "^10.1.8",
50 | "eslint-plugin-prettier": "^5.5.4",
51 | "globals": "^16.5.0",
52 | "jiti": "^2.6.1",
53 | "mocha": "^9.2.2",
54 | "node-fetch": "^2.6.0",
55 | "nyc": "^15.1.0",
56 | "prettier": "^3.5.3",
57 | "rollup": "^4.40.0",
58 | "rollup-plugin-dts": "^6.2.1",
59 | "rollup-plugin-polyfill-node": "^0.13.0",
60 | "ts-node": "^10.0.0",
61 | "tslib": "^2.4.0",
62 | "typescript": "~5.4.0",
63 | "typescript-eslint": "^8.46.4"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/examples/react-native/android/app/src/main/jni/MainComponentsRegistry.cpp:
--------------------------------------------------------------------------------
1 | #include "MainComponentsRegistry.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace facebook {
10 | namespace react {
11 |
12 | MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
13 |
14 | std::shared_ptr
15 | MainComponentsRegistry::sharedProviderRegistry() {
16 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
17 |
18 | // Autolinked providers registered by RN CLI
19 | rncli_registerProviders(providerRegistry);
20 |
21 | // Custom Fabric Components go here. You can register custom
22 | // components coming from your App or from 3rd party libraries here.
23 | //
24 | // providerRegistry->add(concreteComponentDescriptorProvider<
25 | // AocViewerComponentDescriptor>());
26 | return providerRegistry;
27 | }
28 |
29 | jni::local_ref
30 | MainComponentsRegistry::initHybrid(
31 | jni::alias_ref,
32 | ComponentFactory *delegate) {
33 | auto instance = makeCxxInstance(delegate);
34 |
35 | auto buildRegistryFunction =
36 | [](EventDispatcher::Weak const &eventDispatcher,
37 | ContextContainer::Shared const &contextContainer)
38 | -> ComponentDescriptorRegistry::Shared {
39 | auto registry = MainComponentsRegistry::sharedProviderRegistry()
40 | ->createComponentDescriptorRegistry(
41 | {eventDispatcher, contextContainer});
42 |
43 | auto mutableRegistry =
44 | std::const_pointer_cast(registry);
45 |
46 | mutableRegistry->setFallbackComponentDescriptor(
47 | std::make_shared(
48 | ComponentDescriptorParameters{
49 | eventDispatcher, contextContainer, nullptr}));
50 |
51 | return registry;
52 | };
53 |
54 | delegate->buildRegistryFunction = buildRegistryFunction;
55 | return instance;
56 | }
57 |
58 | void MainComponentsRegistry::registerNatives() {
59 | registerHybrid({
60 | makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
61 | });
62 | }
63 |
64 | } // namespace react
65 | } // namespace facebook
66 |
--------------------------------------------------------------------------------
/packages/proton-web-sdk/README.md:
--------------------------------------------------------------------------------
1 | # Proton Web SDK
2 |
3 | Installation
4 | ```
5 | npm i @proton/web-sdk
6 | yarn add @proton/web-sdk
7 | ```
8 |
9 | Usage
10 | ```javascript
11 | import ProtonWebSDK from '@proton/web-sdk'
12 |
13 | // Constants
14 | const appIdentifier = 'taskly'
15 |
16 | // Login
17 | const { link, session } = await ProtonWebSDK({
18 | linkOptions: {
19 | /* RPC endpoints */
20 | endpoints: ['https://proton.greymass.com'],
21 |
22 | /* Recommended: false if first time connecting, true if trying to reconnect */
23 | restoreSession: false
24 | },
25 | transportOptions: {
26 | /* Recommended: Your proton account */
27 | requestAccount: appIdentifier,
28 |
29 | /* Optional: Display request success and error messages, Default true */
30 | requestStatus: true,
31 | },
32 | selectorOptions: {
33 | /* Optional: Name to show in modal, Default 'app' */
34 | appName: 'Taskly',
35 |
36 | /* Optional: Logo to show in modal */
37 | appLogo: 'https://protondemos.com/static/media/taskly-logo.ad0bfb0f.svg',
38 |
39 | /* Optional: Custom style options for modal */
40 | customStyleOptions: {
41 | modalBackgroundColor: '#F4F7FA',
42 | logoBackgroundColor: 'white',
43 | isLogoRound: true,
44 | optionBackgroundColor: 'white',
45 | optionFontColor: 'black',
46 | primaryFontColor: 'black',
47 | secondaryFontColor: '#6B727F',
48 | linkColor: '#752EEB'
49 | }
50 | }
51 | })
52 |
53 | // Actor and permission
54 | console.log(session.auth.actor) // e.g. "metal"
55 | console.log(session.auth.permission) // e.g. "active"
56 |
57 | // Send Transaction
58 | const result = await session.transact({
59 | transaction: {
60 | actions: [{
61 | // Token contract for XUSDT
62 | account: 'xtokens',
63 |
64 | // Action name
65 | name: 'transfer',
66 |
67 | // Action parameters
68 | data: {
69 | from: session.auth.actor,
70 | to: 'token.burn',
71 | quantity: '0.000001 XUSDT',
72 | memo: 'Tip!'
73 | },
74 | authorization: [session.auth]
75 | }]
76 | },
77 | }, { broadcast: true })
78 | console.log('Transaction ID', result.processed.id)
79 |
80 | // Logout
81 | await link.removeSession(appIdentifier, session.auth)
82 | link = undefined
83 | session = undefined
84 | ```
85 |
--------------------------------------------------------------------------------
/examples/vue/src/components/Transfer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
15 |
16 |
17 |
18 |
19 |
21 |
22 |
28 |
29 |
30 |
31 |
33 |
34 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/examples/react-native/App.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | *
5 | * Generated with the TypeScript template
6 | * https://github.com/react-native-community/react-native-template-typescript
7 | *
8 | * @format
9 | */
10 |
11 | import React, {useState} from 'react';
12 | import {
13 | Button,
14 | SafeAreaView,
15 | ScrollView,
16 | StatusBar,
17 | StyleSheet,
18 | Text,
19 | useColorScheme,
20 | View,
21 | } from 'react-native';
22 |
23 | import {Colors, Header} from 'react-native/Libraries/NewAppScreen';
24 | import {sdk} from './webSdk';
25 |
26 | const App = () => {
27 | const [auth, setAuth] = useState({});
28 |
29 | const isDarkMode = useColorScheme() === 'dark';
30 |
31 | const backgroundStyle = {
32 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
33 | };
34 |
35 | return (
36 |
37 |
41 |
44 |
45 |
49 | Proton SDK example
50 | Auth: {JSON.stringify(auth)}
51 |
52 | {Object.keys(auth).length > 0 ? (
53 | <>
54 |
80 |
81 |
82 | );
83 | };
84 |
85 | const styles = StyleSheet.create({
86 | welcome: {
87 | fontSize: 20,
88 | textAlign: 'center',
89 | margin: 10,
90 | },
91 | instructions: {
92 | textAlign: 'center',
93 | color: '#333333',
94 | marginBottom: 5,
95 | },
96 | });
97 |
98 | export default App;
99 |
--------------------------------------------------------------------------------
/examples/vue/src/components/Avatar.vue:
--------------------------------------------------------------------------------
1 |
2 |
40 |
41 |
42 |
70 |
71 |
72 |
--------------------------------------------------------------------------------