Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ledger UI #32

Merged
merged 35 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f25fdae
Modal opening
arhtudormorar Nov 11, 2024
be130f5
Modal opening
arhtudormorar Nov 11, 2024
62d84e0
Fetching address working
arhtudormorar Nov 12, 2024
26713ef
get accounts working
arhtudormorar Nov 12, 2024
b8da059
get accounts working
arhtudormorar Nov 12, 2024
6a423b6
get accounts working
arhtudormorar Nov 12, 2024
d05f7d2
remove log
arhtudormorar Nov 12, 2024
363010f
get accounts working
arhtudormorar Nov 12, 2024
af7fe5c
Pagination working
arhtudormorar Nov 12, 2024
2a14d63
Show spinner while addresses are loading
arhtudormorar Nov 12, 2024
0346572
Make previous button disabled
arhtudormorar Nov 12, 2024
7ad3f21
Fix request update
arhtudormorar Nov 13, 2024
6dd1fea
Make access button disabled conditionally
arhtudormorar Nov 13, 2024
50ff5a2
Login working
arhtudormorar Nov 13, 2024
63245f1
Ledger logging in
arhtudormorar Nov 14, 2024
e961e79
Minor refactors
arhtudormorar Nov 14, 2024
eae460e
Refactor code structure
arhtudormorar Nov 14, 2024
f3e3fd3
Confirm screen working
arhtudormorar Nov 14, 2024
ffdb4d3
Tm/feature/ledger UI communication (#30)
arhtudormorar Nov 20, 2024
a7f1fba
Refactor login with connect screen
arhtudormorar Nov 21, 2024
161300c
Recursive ledger reconnect
arhtudormorar Nov 21, 2024
17259cd
Minor refactor
arhtudormorar Nov 21, 2024
19533aa
Minor refactor
arhtudormorar Nov 22, 2024
956bd11
Better error handling
arhtudormorar Nov 22, 2024
abf5cc5
Update closed ledger flow
arhtudormorar Nov 22, 2024
b1211ad
Minor refactor
arhtudormorar Nov 22, 2024
d5adf83
Project building
arhtudormorar Nov 22, 2024
1794d2b
Use new provider
arhtudormorar Nov 25, 2024
21de575
Remove callbackUrl
arhtudormorar Nov 25, 2024
fa60d95
Merge pull request #31 from multiversx/tm/feature/idapp-provider
arhtudormorar Nov 25, 2024
f423ba1
Remove unused
arhtudormorar Nov 25, 2024
7a60e9f
Fixed eslint
arhtudormorar Nov 25, 2024
68a270e
Update getAddress
arhtudormorar Nov 25, 2024
fd4b10d
Fix import
arhtudormorar Nov 25, 2024
774f3ac
Update getAuthTokenText.ts
arhtudormorar Nov 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 38 additions & 24 deletions eslint.config.js → eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
[
import globals from 'globals';
import pluginJs from '@eslint/js';
import tseslint from 'typescript-eslint';
import importPlugin from 'eslint-plugin-import';
import prettierPlugin from 'eslint-plugin-prettier';

/** @type {import('eslint').Linter.Config[]} */
export default [
{
env: {
es2021: true,
node: true
},
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2021,
sourceType: 'module',
ecmaFeatures: {
jsx: true
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
languageOptions: {
globals: {
...globals.browser,
...globals.node
},
project: './tsconfig.json'
parser: tseslint.parser,
parserOptions: {
ecmaVersion: 2021,
sourceType: 'module',
ecmaFeatures: {
jsx: true
},
project: './tsconfig.json'
}
},
plugins: {
import: importPlugin,
prettier: prettierPlugin,
'@typescript-eslint': tseslint.plugin
},
settings: {
'import/parsers': {
Expand All @@ -27,13 +42,9 @@
}
}
},
extends: [
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended'
],
plugins: ['prettier', 'import'],
rules: {
...pluginJs.configs.recommended.rules,
...tseslint.configs.recommended.rules,
'import/order': [
'warn',
{
Expand All @@ -52,12 +63,7 @@
}
}
],
'prettier/prettier': [
'error',
{
endOfLine: 'lf'
}
],
'prettier/prettier': ['error', { endOfLine: 'lf' }],
'@typescript-eslint/indent': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-use-before-define': [
Expand All @@ -75,6 +81,14 @@
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'no-unused-vars': [
'error',
{
varsIgnorePattern: '^_',
argsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_'
}
],
'object-curly-newline': 'off',
'arrow-body-style': 'off',
'implicit-arrow-linebreak': 'off',
Expand Down
25 changes: 14 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@multiversx/sdk-web-wallet-iframe-provider": "2.0.1",
"@multiversx/sdk-web-wallet-provider": "3.2.1",
"isomorphic-fetch": "3.0.0",
"lit": "3.2.1",
"lodash": "4.17.21",
"protobufjs": "7.3.0",
"socket.io-client": "4.7.5",
Expand All @@ -59,6 +60,7 @@
"string-width": "4.1.0"
},
"devDependencies": {
"@eslint/js": "9.15.0",
"@multiversx/sdk-core": ">= 13.5.0",
"@multiversx/sdk-dapp-utils": "1.0.0",
"@multiversx/sdk-web-wallet-cross-window-provider": ">= 2.0.1",
Expand All @@ -67,22 +69,22 @@
"@types/jest": "29.5.13",
"@types/lodash": "4.17.4",
"@types/node": "20.12.8",
"@typescript-eslint/eslint-plugin": "7.8.0",
"@typescript-eslint/parser": "7.8.0",
"@typescript-eslint/eslint-plugin": "8.15.0",
"@typescript-eslint/parser": "8.15.0",
"axios": ">=1.6.5",
"axios-mock-adapter": "^1.22.0",
"axios-mock-adapter": "1.22.0",
"bignumber.js": "9.x",
"esbuild": "^0.21.1",
"esbuild": "0.21.1",
"esbuild-node-externals": "1.14.0",
"eslint": "9.1.1",
"eslint": "9.15.0",
"eslint-config-prettier": "9.1.0",
"eslint-config-standard": "17.1.0",
"eslint-import-resolver-typescript": "3.6.1",
"eslint-plugin-import": "2.29.1",
"eslint-import-resolver-typescript": "3.6.3",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-prettier": "5.1.3",
"eslint-plugin-promise": "6.1.1",
"glob": "^10.3.14",
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-promise": "7.1.0",
"glob": "10.3.14",
"immer": "^10.1.1",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
Expand All @@ -93,6 +95,7 @@
"rimraf": "^5.0.6",
"ts-jest": "29.1.2",
"tsc-alias": "^1.8.9",
"typescript": "^5.4.5"
"typescript": "5.4.5",
"typescript-eslint": "8.15.0"
}
}
1 change: 1 addition & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './window.constants';
export * from './browser.constants';
export * from './errorMessages.constants';
export * from './mvx.constants';
export * from './ledger.constants';
94 changes: 94 additions & 0 deletions src/constants/ledger.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
export const LEDGER_MULTI_ACCOUNT_MINIMUM_VERSION = '1.0.8';
export const LEDGER_HASH_SIGN_MINIMUM_VERSION = '1.0.11';
export const LEDGER_SIGN_AUTH_TOKEN_MINIMUM_VERSION = '1.0.15';
export const LEDGER_WITH_WHITELISTED_TOKENS_MINIMUM_VERSION = '1.0.17';
export const LEDGER_WITH_GUARDIANS_MINIMUM_VERSION = '1.0.22';
export const LEDGER_WITH_USERNAMES_MINIMUM_VERSION = '1.0.23';

export const ledgerErrorCodes = {
0x9000: {
code: 'codeSuccess',
message: 'Success'
},
0x6985: {
code: 'ERR_USER_DENIED',
message: 'Rejected by user'
},
0x6d00: {
code: 'ERR_UNKNOWN_INSTRUCTION',
message: 'Unknown instruction'
},
0x6e00: {
code: 'ERR_WRONG_CLA',
message: 'Wrong CLA'
},
0x6e01: {
code: 'ERR_INVALID_ARGUMENTS',
message: 'Invalid arguments'
},
0x6e02: {
code: 'ERR_INVALID_MESSAGE',
message: 'Invalid message'
},
0x6e03: {
code: 'ERR_INVALID_P1',
message: 'Invalid P1'
},
0x6e04: {
code: 'ERR_MESSAGE_TOO_LONG',
message: 'Message too long'
},
0x6e05: {
code: 'ERR_RECEIVER_TOO_LONG',
message: 'Receiver too long'
},
0x6e06: {
code: 'ERR_AMOUNT_TOO_LONG',
message: 'Amount too long'
},
0x6e07: {
code: 'ERR_CONTRACT_DATA_DISABLED',
message: 'Contract data disabled in app options'
},
0x6e08: {
code: 'ERR_MESSAGE_INCOMPLETE',
message: 'Message incomplete'
},
0x6e10: {
code: 'ERR_SIGNATURE_FAILED',
message: 'Signature failed'
},
0x6e09: {
code: 'ERR_WRONG_TX_VERSION',
message: 'Wrong TX version'
},
0x6e0a: {
code: 'ERR_NONCE_TOO_LONG',
message: 'Nonce too long'
},
0x6e0b: {
code: 'ERR_INVALID_AMOUNT',
message: 'Invalid amount'
},
0x6e0c: {
code: 'ERR_INVALID_FEE',
message: 'Invalid fee'
},
0x6e0d: {
code: 'ERR_PRETTY_FAILED',
message: 'Pretty failed'
},
0x6e0e: {
code: 'ERR_DATA_TOO_LONG',
message: 'Data too long'
},
0x6e0f: {
code: 'ERR_WRONG_TX_OPTIONS',
message: 'Invalid transaction options'
},
0x6e11: {
code: 'ERR_SIGN_TX_DEPRECATED',
message:
'Regular transaction signing is deprecated in this version. Use hash signing.'
}
};
1 change: 0 additions & 1 deletion src/core/methods/account/getIsLoggedIn.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { isLoggedInSelector } from 'store/selectors/accountSelectors';
import { getAddress } from './getAddress';
import { getState } from 'store/store';

export function getIsLoggedIn() {
Expand Down
81 changes: 81 additions & 0 deletions src/core/providers/DappProvider/DappProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Message } from '@multiversx/sdk-core/out/message';
import { Transaction } from '@multiversx/sdk-core/out/transaction';
import { IProvider } from '../types/providerFactory.types';
import { login } from './helpers/login/login';
import { logout } from './helpers/logout/logout';
import { signMessage } from './helpers/signMessage/signMessage';
import {
verifyMessage,
VerifyMessageReturnType
} from './helpers/signMessage/verifyMessage';
import {
signTransactions,
SignTransactionsOptionsType
} from './helpers/signTransactions/signTransactions';

export class DappProvider {
private provider: IProvider;

constructor(provider: IProvider) {
this.provider = provider;
}

init() {
return this.provider.init();
}

async login() {
return await login(this.provider);
}

async logout(
options = {
shouldBroadcastLogoutAcrossTabs: true,
hasConsentPopup: false
}
) {
return await logout({ provider: this.provider, options });
}

setShouldShowConsentPopup(shouldShow: boolean) {
this.provider.setShouldShowConsentPopup?.(shouldShow);
}

getType() {
return this.provider.getType();
}

getProvider() {
return this.provider;
}

async signTransactions(
transactions: Transaction[],
options?: SignTransactionsOptionsType
): Promise<Transaction[]> {
const signedTransactions = await signTransactions({
provider: this.provider,
transactions,
options
});
return signedTransactions;
}

async signMessage(
message: Message,
options?: {
hasConsentPopup?: boolean;
}
): Promise<Message | null> {
const signedMessage = await signMessage({
provider: this.provider,
message,
options
});
return signedMessage;
}

verifyMessage(signedMessage: string): VerifyMessageReturnType {
return verifyMessage(signedMessage);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Address, SignableMessage } from '@multiversx/sdk-core';
import { Address, Message } from '@multiversx/sdk-core';
import { nativeAuth } from 'services/nativeAuth';
import { buildNativeAuthConfig } from 'services/nativeAuth/methods';
import { networkSelector, tokenLoginSelector } from 'store/selectors';
import { getState } from 'store/store';
import { OnProviderLoginType } from 'types/login.types';
import { getAccount } from '../../account/getAccount';
import { setTokenLogin } from 'store/actions/loginInfo/loginInfoActions';
import { NativeAuthConfigType } from 'services/nativeAuth/nativeAuth.types';
import { getAccount } from 'core/methods/account/getAccount';

const getApiAddress = (
apiAddress: string,
Expand Down Expand Up @@ -99,9 +99,9 @@ export function getLoginService(config?: OnProviderLoginType['nativeAuth']) {
nativeAuthClientConfig
}: {
signMessageCallback: (
messageToSign: SignableMessage,
messageToSign: Message,
options: Record<any, any>
) => Promise<SignableMessage>;
) => Promise<Message>;
nativeAuthClientConfig?: NativeAuthConfigType;
}) => {
const { address } = getAccount();
Expand All @@ -115,17 +115,25 @@ export function getLoginService(config?: OnProviderLoginType['nativeAuth']) {
});

tokenRef = loginToken;

if (!loginToken) {
return;
}
const messageToSign = new SignableMessage({

const messageToSign = new Message({
address: new Address(address),
message: Buffer.from(`${address}${loginToken}`)
data: Buffer.from(`${address}${loginToken}`)
});

const signedMessage = await signMessageCallback(messageToSign, {});

if (!signedMessage?.signature) {
throw 'Message not signed';
}

const nativeAuthToken = setTokenLoginInfo({
address,
signature: signedMessage.getSignature().toString('hex')
signature: Buffer.from(signedMessage.signature).toString('hex')
});

return nativeAuthToken;
Expand Down
Loading
Loading