diff --git a/package.json b/package.json index e4f9bfa..6989c68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-dapp-core", - "version": "0.0.0-alpha.10", + "version": "0.0.0-alpha.11", "main": "out/index.js", "module": "out/index.js", "types": "out/index.d.ts", diff --git a/src/core/providers/ProviderFactory.ts b/src/core/providers/ProviderFactory.ts index 0b8104b..c5eeb64 100644 --- a/src/core/providers/ProviderFactory.ts +++ b/src/core/providers/ProviderFactory.ts @@ -1,7 +1,5 @@ import { IframeLoginTypes } from '@multiversx/sdk-web-wallet-iframe-provider/out/constants'; -import { SECOND_LOGIN_ATTEMPT_ERROR } from 'constants/errorMessages.constants'; import { getAddress } from 'core/methods/account/getAddress'; -import { getIsLoggedIn } from 'core/methods/account/getIsLoggedIn'; import { setProviderType } from 'store/actions/loginInfo/loginInfoActions'; import { setAccountProvider } from './accountProvider'; import { DappProvider } from './DappProvider/DappProvider'; @@ -62,13 +60,6 @@ export class ProviderFactory { createdProvider.getType = () => ProviderTypeEnum.ledger; - const loggedIn = getIsLoggedIn(); - - if (loggedIn) { - console.warn('Already logged in with:', getAddress()); - throw new Error(SECOND_LOGIN_ATTEMPT_ERROR); - } - await createdProvider.init?.(); break; diff --git a/src/core/providers/helpers/ledger/createLedgerProvider.ts b/src/core/providers/helpers/ledger/createLedgerProvider.ts index d7c1f20..f5fde37 100644 --- a/src/core/providers/helpers/ledger/createLedgerProvider.ts +++ b/src/core/providers/helpers/ledger/createLedgerProvider.ts @@ -1,3 +1,4 @@ +import { Transaction } from '@multiversx/sdk-core/out'; import BigNumber from 'bignumber.js'; import { safeWindow } from 'constants/window.constants'; import { getIsLoggedIn } from 'core/methods/account/getIsLoggedIn'; @@ -6,7 +7,11 @@ import { IProvider, ProviderTypeEnum } from 'core/providers/types/providerFactory.types'; -import { defineCustomElements, LedgerConnectModal } from 'lib/sdkDappCoreUi'; +import { + defineCustomElements, + LedgerConnectModal, + SignTransactionsModal +} from 'lib/sdkDappCoreUi'; import { setLedgerAccount } from 'store/actions/account/accountActions'; import { setLedgerLogin } from 'store/actions/loginInfo/loginInfoActions'; import { fetchAccount } from 'utils/account/fetchAccount'; @@ -16,6 +21,8 @@ import { getLedgerProvider } from './helpers/getLedgerProvider'; import { LedgerConnectStateManager } from './helpers/LedgerConnectStateManager'; import { LedgerConnectEventsEnum } from './ledger.types'; import { ILedgerAccount } from './ledger.types'; +import { SignEventsEnum } from '../components/SignTransactionsModal/signTransactionsModal.types'; +import { SignTransactionsStateManager } from '../components/SignTransactionsModal/SignTransactionsStateManager'; const failInitializeErrorText = 'Check if the MultiversX App is open on Ledger'; @@ -78,6 +85,77 @@ export async function createLedgerProvider(): Promise { createdProvider.getType = () => ProviderTypeEnum.ledger; + createdProvider.signTransactions = async ( + transactions: Transaction[] + ): Promise => { + const { ledgerProvider: customProvider } = await getLedgerProvider(); + + // TODO: extract to method what is below + const signModalElement = document.createElement( + 'sign-transactions-modal' + ) as SignTransactionsModal; + + document.body.appendChild(signModalElement); + await customElements.whenDefined('sign-transactions-modal'); + + const eventBus = await signModalElement.getEventBus(); + + const manager = SignTransactionsStateManager.getInstance(eventBus); + if (!manager) { + throw new Error('Unable to establish connection with sign screens'); + } + + return new Promise(async (resolve, reject) => { + const signedTransactions: Transaction[] = []; + let currentTransactionIndex = 0; + + const signNextTransaction = async () => { + const currentTransaction = transactions[currentTransactionIndex]; + + manager.updateTransaction({ + transaction: currentTransaction.toPlainObject() + }); + + const onCancel = () => { + reject(new Error('Transaction signing cancelled by user')); + signModalElement.remove(); + }; + + const onSign = async () => { + try { + // TODO: check if it's a real transaction or multitransfer step + const [signedTransaction] = await customProvider.signTransactions([ + currentTransaction + ]); + + if (signedTransaction) { + signedTransactions.push(signedTransaction); + } + + eventBus.unsubscribe(SignEventsEnum.SIGN_TRANSACTION, onSign); + eventBus.unsubscribe(SignEventsEnum.CLOSE, onCancel); + + if (signedTransactions.length == transactions.length) { + signModalElement.remove(); + resolve(signedTransactions); + } else { + currentTransactionIndex++; + signNextTransaction(); + } + } catch (error) { + reject('Error signing transactions: ' + error); + signModalElement.remove(); + } + }; + + eventBus.subscribe(SignEventsEnum.SIGN_TRANSACTION, onSign); + eventBus.subscribe(SignEventsEnum.CLOSE, onCancel); + }; + + signNextTransaction(); + }); + }; + createdProvider.login = async (options?: { callbackUrl?: string; token?: string;