UNPKG

stellar-plus

Version:

beta version of stellar-plus, an all-in-one sdk for the Stellar blockchain

308 lines (307 loc) 18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const freighterApi = tslib_1.__importStar(require("@stellar/freighter-api")); const stellar_sdk_1 = require("@stellar/stellar-sdk"); const freighter_1 = require("../../../../stellar-plus/account/account-handler/freighter"); const errors_1 = require("../../../../stellar-plus/account/account-handler/freighter/errors"); const network_1 = require("../../../../stellar-plus/network"); jest.mock('@stellar/freighter-api', () => ({ getPublicKey: jest.fn(), isConnected: jest.fn(), isAllowed: jest.fn(), setAllowed: jest.fn().mockResolvedValue(true), signTransaction: jest.fn(), getNetworkDetails: jest.fn(), signAuthEntry: jest.fn(), })); const MOCKED_GET_PUBLIC_KEY = freighterApi.getPublicKey; const MOCKED_IS_CONNECTED = freighterApi.isConnected; const MOCKED_IS_ALLOWED = freighterApi.isAllowed; const MOCKED_SET_ALLOWED = freighterApi.setAllowed; const MOCKED_SIGN_TRANSACTION = freighterApi.signTransaction; const MOCKED_GET_NETWORK_DETAILS = freighterApi.getNetworkDetails; const MOCKED_SIGN_AUTH_ENTRY = freighterApi.signAuthEntry; const mockFreighterIsInstalled = (status) => { MOCKED_IS_CONNECTED.mockResolvedValue(status); }; const mockFreighterIsAllowed = (status) => { MOCKED_IS_ALLOWED.mockResolvedValue(status); }; const mockFreighterGetPublicKey = (pk) => { MOCKED_GET_PUBLIC_KEY.mockResolvedValue(pk); }; const mockFreighterGetNetworkDetailsTestnet = () => { MOCKED_GET_NETWORK_DETAILS.mockResolvedValue({ networkPassphrase: (0, network_1.TestNet)().networkPassphrase }); }; const mockFreighterGetNetworkDetailsWrongNetwork = () => { MOCKED_GET_NETWORK_DETAILS.mockResolvedValue({ networkPassphrase: 'wrong network' }); }; const TESTNET_CONFIG = (0, network_1.TestNet)(); const MOCKED_PK = 'GAUFIAL2LV2OV7EA4NTXZDVPQASGI5Y3EXZV2HQS3UUWMZ7UWJDQURYS'; describe('FreighterAccountHandlerClient', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Initialization', () => { it('should initialize with the networkConfig', () => { const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); expect(fah).toBeDefined(); }); }); describe('Connect', () => { it('should load and set the public key when connected', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetNetworkDetailsTestnet(); mockFreighterGetPublicKey(MOCKED_PK); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.connect(); expect(MOCKED_IS_CONNECTED).toHaveBeenCalled(); expect(MOCKED_IS_ALLOWED).toHaveBeenCalled(); expect(MOCKED_GET_PUBLIC_KEY).toHaveBeenCalled(); expect(MOCKED_GET_NETWORK_DETAILS).toHaveBeenCalled(); expect(fah.getPublicKey()).toBe(MOCKED_PK); })); it('should trigger permission if extension is not allowed', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(false); mockFreighterGetNetworkDetailsTestnet(); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.connect(); expect(MOCKED_IS_CONNECTED).toHaveBeenCalled(); expect(MOCKED_SET_ALLOWED).toHaveBeenCalled(); expect(MOCKED_GET_PUBLIC_KEY).not.toHaveBeenCalled(); expect(MOCKED_GET_NETWORK_DETAILS).not.toHaveBeenCalled(); expect(fah.getPublicKey()).toBe(''); })); it('should trigger permission if extension is not allowed then load the public key and call the provided callback', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); MOCKED_IS_ALLOWED.mockResolvedValue(true).mockResolvedValueOnce(false); // will return false once then only true const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); const mockedCallBack = jest.fn().mockImplementationOnce((pk) => { // Necessary to break AAA here to ensure assertion only when callback is called expect(MOCKED_GET_PUBLIC_KEY).toHaveBeenCalled(); expect(pk).toBe(MOCKED_PK); expect(mockedCallBack).toHaveBeenCalledExactlyOnceWith(MOCKED_PK); expect(MOCKED_IS_CONNECTED).toHaveBeenCalledTimes(2); expect(MOCKED_IS_ALLOWED).toHaveBeenCalledTimes(2); expect(MOCKED_SET_ALLOWED).toHaveBeenCalledOnce(); }); yield fah.connect(mockedCallBack); })); it('should not load public key if extension is allowed to the wrong network', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsWrongNetwork(); mockFreighterIsAllowed(true); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.connect(); expect(MOCKED_IS_CONNECTED).toHaveBeenCalledOnce(); expect(MOCKED_IS_ALLOWED).toHaveBeenCalledOnce(); expect(MOCKED_GET_NETWORK_DETAILS).toHaveBeenCalledOnce(); expect(MOCKED_GET_PUBLIC_KEY).not.toHaveBeenCalled(); expect(fah.getPublicKey()).toBe(''); })); describe('Disconnect', () => { it('should reset the publick key', () => { const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); // eslint-disable-next-line @typescript-eslint/no-explicit-any jest.replaceProperty(fah, 'publicKey', MOCKED_PK); fah.disconnect(); expect(fah.getPublicKey()).toBe(''); }); }); }); describe('Load Public Key', () => { it('should not load the public key if freighter is not installed', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(false); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); expect(MOCKED_SET_ALLOWED).not.toHaveBeenCalled(); expect(MOCKED_GET_PUBLIC_KEY).not.toHaveBeenCalled(); expect(fah.getPublicKey()).toBe(''); })); it('should not load the public key if freighter is installed but not allowed', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(false); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); expect(MOCKED_SET_ALLOWED).not.toHaveBeenCalled(); expect(MOCKED_GET_PUBLIC_KEY).not.toHaveBeenCalled(); expect(fah.getPublicKey()).toBe(''); })); it('should not load the public key if freighter is connected to the wrong network', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetNetworkDetailsWrongNetwork(); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); expect(MOCKED_SET_ALLOWED).not.toHaveBeenCalled(); expect(MOCKED_GET_PUBLIC_KEY).not.toHaveBeenCalled(); expect(fah.getPublicKey()).toBe(''); })); it('should load the public key if freighter is installed and allowed', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetNetworkDetailsTestnet(); mockFreighterGetPublicKey(MOCKED_PK); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); expect(MOCKED_GET_PUBLIC_KEY).toHaveBeenCalled(); expect(fah.getPublicKey()).toBe(MOCKED_PK); })); it('should trigger permission when enforceConnection is true and then load the public key and trigger the callback', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); MOCKED_IS_ALLOWED.mockResolvedValue(true).mockResolvedValueOnce(false); // will return false once then only true const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); const mockedCallBack = jest.fn().mockImplementationOnce((pk) => { // Necessary to break AAA here to ensure assertion only when callback is called expect(MOCKED_GET_PUBLIC_KEY).toHaveBeenCalled(); expect(pk).toBe(MOCKED_PK); expect(mockedCallBack).toHaveBeenCalledExactlyOnceWith(MOCKED_PK); expect(MOCKED_IS_CONNECTED).toHaveBeenCalledTimes(2); expect(MOCKED_IS_ALLOWED).toHaveBeenCalledTimes(2); expect(MOCKED_SET_ALLOWED).toHaveBeenCalledOnce(); }); yield fah.loadPublicKey(mockedCallBack, true); })); }); describe('Core signing features', () => { it('should sign a transaction with freighter', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); MOCKED_SIGN_TRANSACTION.mockResolvedValue('signedTx'); const mockedTx = { toXDR: jest.fn().mockReturnValue('mocked xdr'), }; const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); const signedTx = yield fah.sign(mockedTx); expect(mockedTx.toXDR).toHaveBeenCalledOnce(); expect(MOCKED_SIGN_TRANSACTION).toHaveBeenCalledExactlyOnceWith('mocked xdr', { networkPassphrase: TESTNET_CONFIG.networkPassphrase, accountToSign: MOCKED_PK, }); expect(signedTx).toBe('signedTx'); })); it('should sign a fee bump transaction with freighter', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); MOCKED_SIGN_TRANSACTION.mockResolvedValue('signedTx'); const mockedTx = { toXDR: jest.fn().mockReturnValue('mocked xdr'), }; const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); const signedTx = yield fah.sign(mockedTx); expect(mockedTx.toXDR).toHaveBeenCalledOnce(); expect(MOCKED_SIGN_TRANSACTION).toHaveBeenCalledExactlyOnceWith('mocked xdr', { networkPassphrase: TESTNET_CONFIG.networkPassphrase, accountToSign: MOCKED_PK, }); expect(signedTx).toBe('signedTx'); })); it('should sign a soroban authorization entry with freighter', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); MOCKED_SIGN_AUTH_ENTRY.mockResolvedValue('signedAuthEntry'); const mockedAuthEntry = { credentials: jest.fn(), rootInvocation: jest.fn(), toXDR: jest.fn().mockReturnValue('mocked xdr'), }; const spyXdr = jest.spyOn(stellar_sdk_1.xdr.SorobanAuthorizationEntry, 'fromXDR').mockImplementationOnce(() => mockedAuthEntry); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); const signedAuthEntry = yield fah.signSorobanAuthEntry(mockedAuthEntry, 0, TESTNET_CONFIG.networkPassphrase); expect(mockedAuthEntry.toXDR).toHaveBeenCalledOnce(); expect(MOCKED_SIGN_AUTH_ENTRY).toHaveBeenCalledExactlyOnceWith('mocked xdr', { accountToSign: MOCKED_PK, }); expect(spyXdr).toHaveBeenCalledExactlyOnceWith('signedAuthEntry', 'base64'); expect(signedAuthEntry).toBe(mockedAuthEntry); })); }); describe('Errors', () => { const MOCKED_ERROR = new Error('mocked error'); it('should throw when failed to load public key', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetNetworkDetailsTestnet(); MOCKED_GET_PUBLIC_KEY.mockRejectedValue(MOCKED_ERROR); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield expect(fah.loadPublicKey()).rejects.toThrow(errors_1.FAHError.failedToLoadPublicKeyError(MOCKED_ERROR)); })); it('should throw when failed to sign transaction', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); const mockedTx = { toXDR: jest.fn().mockReturnValue('mocked xdr'), }; MOCKED_SIGN_TRANSACTION.mockRejectedValue(MOCKED_ERROR); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); yield expect(fah.sign(mockedTx)).rejects.toThrow(errors_1.FAHError.failedToSignTransactionError(MOCKED_ERROR)); })); it('should throw when trying to sign a transaction with Freighter when it is not connected', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(false); const mockedTx = { toXDR: jest.fn().mockReturnValue('mocked xdr'), }; const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield expect(fah.sign(mockedTx)).rejects.toThrow(errors_1.FAHError.freighterIsNotConnectedError()); })); it('should throw when failed to sign a soroban authorization entry', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); const mockedAuthEntry = { credentials: jest.fn(), rootInvocation: jest.fn(), toXDR: jest.fn().mockReturnValue('mocked xdr'), }; MOCKED_SIGN_AUTH_ENTRY.mockRejectedValue(MOCKED_ERROR); const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); yield expect(fah.signSorobanAuthEntry(mockedAuthEntry, 0, TESTNET_CONFIG.networkPassphrase)).rejects.toThrow(errors_1.FAHError.failedToSignAuthEntryError(MOCKED_ERROR)); })); it('should throw when trying to sign a soroban authorization entry with Freighter when it is not connected', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(false); const mockedAuthEntry = { credentials: jest.fn(), rootInvocation: jest.fn(), toXDR: jest.fn().mockReturnValue('mocked xdr'), }; const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield expect(fah.signSorobanAuthEntry(mockedAuthEntry, 0, TESTNET_CONFIG.networkPassphrase)).rejects.toThrow(errors_1.FAHError.freighterIsNotConnectedError()); })); it('should throw when trying to sign a soroban authorization entry with Freighter when it is connected to a different network than the one requested to sign for', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { mockFreighterIsInstalled(true); mockFreighterIsAllowed(true); mockFreighterGetPublicKey(MOCKED_PK); mockFreighterGetNetworkDetailsTestnet(); const mockedAuthEntry = { credentials: jest.fn(), rootInvocation: jest.fn(), toXDR: jest.fn().mockReturnValue('mocked xdr'), }; const fah = new freighter_1.FreighterAccountHandlerClient({ networkConfig: TESTNET_CONFIG }); yield fah.loadPublicKey(); yield expect(fah.signSorobanAuthEntry(mockedAuthEntry, 0, 'wrong network')).rejects.toThrow(errors_1.FAHError.cannotSignForThisNetwork('wrong network', TESTNET_CONFIG.networkPassphrase)); })); }); });