diff --git a/.storybook/example.stories.js b/.storybook/example.stories.js
index bbfe2ab7..3fd20426 100644
--- a/.storybook/example.stories.js
+++ b/.storybook/example.stories.js
@@ -54,20 +54,6 @@ stories.add('Component', () => {
);
});
-stories.add('web3', () => {
- const props = {
- token: text('token', ''),
- };
-
- button('Save Link configuration', reRender);
-
- return (
-
-
-
- );
-});
-
stories.add('embedded Link', () => {
const props = {
token: text('token', ''),
diff --git a/Makefile b/Makefile
index 9beec787..d182b25a 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ SRC_FILES = $(shell find src -name '*.js|*.tsx|*.ts' | sort)
.PHONY: clean
clean:
- @rm -rf dist lib web3
+ @rm -rf dist lib
.PHONY: build
diff --git a/examples/web3.tsx b/examples/web3.tsx
deleted file mode 100644
index 27eb735c..00000000
--- a/examples/web3.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import React, { useCallback } from 'react';
-
-import {
- useEthereumProvider,
- EthereumOnboardingOptions,
- PlaidWeb3OnSuccess,
- EIP1193Provider,
-} from 'react-plaid-link/web3';
-
-import { PlaidLinkOnExit } from 'react-plaid-link';
-
-const PlaidWeb3Link = () => {
- const token = '';
-
- const [walletProvider, setWalletProvider] = React.useState();
- const [addresses, setAddresses] = React.useState();
- const [checkedExistingProvider, setCheckedExistingProvider] = React.useState(
- false
- );
-
- const onSuccess = useCallback(
- async provider => {
- setWalletProvider(provider);
- },
- [setWalletProvider]
- );
- const onExit = useCallback((error, metadata) => {
- // log onExit callbacks from Link, handle errors
- // https://plaid.com/docs/link/web/#onexit
- console.log(error, metadata);
- }, []);
-
- const config: EthereumOnboardingOptions = {
- token,
- chain: {
- chainId: '0x1',
- rpcUrl: 'https://rpc.com',
- },
- onSuccess,
- onExit,
- };
-
- const {
- open,
- ready,
- getCurrentEthereumProvider,
- isProviderActive,
- // error,
- // exit
- } = useEthereumProvider(config);
-
- React.useEffect(() => {
- if (!ready) {
- return;
- }
- (async () => {
- const provider = await getCurrentEthereumProvider(config.chain);
- if (!provider) {
- setCheckedExistingProvider(true);
- return;
- }
- const isActive = await isProviderActive(provider);
- if (isActive) {
- setWalletProvider(provider);
- }
- setCheckedExistingProvider(true);
- })();
-
- return () => {};
- }, [
- ready,
- getCurrentEthereumProvider,
- setCheckedExistingProvider,
- isProviderActive,
- setWalletProvider,
- ]);
-
- React.useEffect(() => {
- if (!walletProvider) {
- return;
- }
- (async () => {
- const addresses = await walletProvider.request({
- method: 'eth_accounts',
- });
- setAddresses(addresses);
- })();
- }, [walletProvider, setAddresses]);
-
- if (addresses) {
- return {addresses.join(', ')};
- }
-
- return (
-
- );
-};
-
-export default PlaidWeb3Link;
diff --git a/package.json b/package.json
index f480637f..4a66a565 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,6 @@
"registry": "https://registry.npmjs.org",
"files": [
"dist",
- "web3",
"src",
"LICENSE"
],
diff --git a/rollup.config.js b/rollup.config.js
index ed18b697..3de86a00 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -23,22 +23,6 @@ export default [
commonjs(),
],
},
- {
- input: 'src/web3/index.ts',
- external: ['react', 'prop-types'],
- output: [
- { file: 'web3/index.js', format: 'cjs' },
- { file: 'web3/index.esm.js', format: 'es' },
- ],
- plugins: [
- ts(),
- resolve(),
- babel({
- extensions: ['.ts', '.tsx'],
- }),
- commonjs(),
- ],
- },
// UMD build with inline PropTypes
{
input: 'src/index.ts',
diff --git a/src/factory.ts b/src/factory.ts
index 570c2d07..e52660c6 100644
--- a/src/factory.ts
+++ b/src/factory.ts
@@ -5,8 +5,6 @@ import {
CommonPlaidLinkOptions,
} from './types';
-import { EthereumOnboardingOptions } from './types/web3';
-
export interface PlaidFactory {
open: (() => void) | Function;
submit: ((data: PlaidHandlerSubmissionData) => void)| Function;
@@ -102,13 +100,6 @@ const createPlaidHandler = >(
};
};
-export const createWeb3Plaid = (
- options: EthereumOnboardingOptions,
- creator: (options: EthereumOnboardingOptions) => PlaidHandler
-) => {
- return createPlaidHandler(options, creator);
-};
-
export const createPlaid = (
options: PlaidLinkOptions,
creator: (options: PlaidLinkOptions) => PlaidHandler
diff --git a/src/types/web3.ts b/src/types/web3.ts
deleted file mode 100644
index c53869b4..00000000
--- a/src/types/web3.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { CommonPlaidLinkOptions, PlaidHandler, Plaid } from './';
-
-import { EIP1193Provider as ImportedEIP1193Provider } from './web3Provider';
-
-export interface PlaidWeb3OnSuccessMetadata {
- link_session_id: string;
- wallet: {
- name: string;
- };
-}
-
-export interface ChainInformation {
- name: string;
- nativeCurrency: {
- name: string;
- symbol: string;
- decimals: number;
- };
- blockExplorerUrls: string[];
-}
-
-export interface ChainOption {
- chainId: string;
- rpcUrl: string;
- chainInformation?: ChainInformation;
-}
-
-export type EIP1193Provider = Omit;
-
-export type PlaidWeb3OnSuccess = (
- provider: EIP1193Provider,
- metadata: PlaidWeb3OnSuccessMetadata
-) => void;
-
-export interface EthereumOnboardingOptions
- extends CommonPlaidLinkOptions {
- token: string | null;
- chain: ChainOption;
-}
-
-export interface PlaidWeb3 {
- createEthereumOnboarding: (config: EthereumOnboardingOptions) => PlaidHandler;
- getCurrentEthereumProvider: (
- chainOption: ChainOption
- ) => Promise;
- isProviderActive: (provider: EIP1193Provider) => Promise;
- disconnectEthereumProvider: (provider: EIP1193Provider) => Promise;
-}
-
-export interface PlaidGlobalWithWeb3 extends Plaid {
- web3: () => Promise;
-}
diff --git a/src/types/web3Provider.d.ts b/src/types/web3Provider.d.ts
deleted file mode 100644
index e9abbcd5..00000000
--- a/src/types/web3Provider.d.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-// This is a partial version of @web3-onboard/common's EIP-1193 type
-// https://github.com/blocknative/web3-onboard/blob/v2-web3-onboard-develop/packages/common/src/types.ts#L345
-// Importing the types via the module would be preferred, but this creates issues when generating a
-// rolled up .d.ts.
-// Specifically, the default rollup-plugin-ts uses the default tsc --declaration output,
-// which does not roll up module type definitions. rollup-plugin-dts only rolls up the immediately
-// imported modules, but does not roll-up nested/transitive modules, which these EIP-1193 types
-// have via the `eip-712` package.
-// So, for now we copy the EIP-1193 types here and change the `eth_signTypedData` type to be
-// `unknown`
-
-declare type ChainId = string;
-interface ProviderRpcError extends Error {
- message: string;
- code: number;
- data?: unknown;
-}
-interface ProviderMessage {
- type: string;
- data: unknown;
-}
-interface ProviderInfo {
- chainId: ChainId;
-}
-declare type AccountAddress = string;
-/**
- * An array of addresses
- */
-declare type ProviderAccounts = AccountAddress[];
-declare type ProviderEvent =
- | 'connect'
- | 'disconnect'
- | 'message'
- | 'chainChanged'
- | 'accountsChanged';
-interface SimpleEventEmitter {
- on(
- event: ProviderEvent,
- listener:
- | ConnectListener
- | DisconnectListener
- | MessageListener
- | ChainListener
- | AccountsListener
- ): void;
- removeListener(
- event: ProviderEvent,
- listener:
- | ConnectListener
- | DisconnectListener
- | MessageListener
- | ChainListener
- | AccountsListener
- ): void;
-}
-declare type ConnectListener = (info: ProviderInfo) => void;
-declare type DisconnectListener = (error: ProviderRpcError) => void;
-declare type MessageListener = (message: ProviderMessage) => void;
-declare type ChainListener = (chainId: ChainId) => void;
-declare type AccountsListener = (accounts: ProviderAccounts) => void;
-/**
- * The hexadecimal representation of the users
- */
-declare type Balance = string;
-interface TransactionObject {
- data?: string;
- from: string;
- gas?: string;
- gasLimit?: string;
- gasPrice?: string;
- to: string;
- chainId: number;
- value?: string;
- maxFeePerGas?: string;
- maxPriorityFeePerGas?: string;
- nonce?: string;
-}
-interface BaseRequest {
- params?: never;
-}
-interface EthAccountsRequest extends BaseRequest {
- method: 'eth_accounts';
-}
-interface EthChainIdRequest extends BaseRequest {
- method: 'eth_chainId';
-}
-interface EthSignTransactionRequest {
- method: 'eth_signTransaction';
- params: [TransactionObject];
-}
-declare type Address = string;
-declare type Message = string;
-interface EthSignMessageRequest {
- method: 'eth_sign';
- params: [Address, Message];
-}
-interface PersonalSignMessageRequest {
- method: 'personal_sign';
- params: [Message, Address];
-}
-interface EIP712Request {
- method: 'eth_signTypedData';
- // This is marked as unknown in this fork
- params: [Address, unknown];
-}
-interface EthBalanceRequest {
- method: 'eth_getBalance';
- params: [string, (number | 'latest' | 'earliest' | 'pending')?];
-}
-interface EIP1102Request extends BaseRequest {
- method: 'eth_requestAccounts';
-}
-interface SelectAccountsRequest extends BaseRequest {
- method: 'eth_selectAccounts';
-}
-interface EIP3085Request {
- method: 'wallet_addEthereumChain';
- params: AddChainParams[];
-}
-interface EIP3326Request {
- method: 'wallet_switchEthereumChain';
- params: [
- {
- chainId: ChainId;
- }
- ];
-}
-declare type AddChainParams = {
- chainId: ChainId;
- chainName?: string;
- nativeCurrency: {
- name?: string;
- symbol?: string;
- decimals: number;
- };
- rpcUrls: string[];
-};
-export interface EIP1193Provider extends SimpleEventEmitter {
- on(event: 'connect', listener: ConnectListener): void;
- on(event: 'disconnect', listener: DisconnectListener): void;
- on(event: 'message', listener: MessageListener): void;
- on(event: 'chainChanged', listener: ChainListener): void;
- on(event: 'accountsChanged', listener: AccountsListener): void;
- request(args: EthAccountsRequest): Promise;
- request(args: EthBalanceRequest): Promise;
- request(args: EIP1102Request): Promise;
- request(args: SelectAccountsRequest): Promise;
- request(args: EIP3326Request): Promise;
- request(args: EIP3085Request): Promise;
- request(args: EthChainIdRequest): Promise;
- request(args: EthSignTransactionRequest): Promise;
- request(args: EthSignMessageRequest): Promise;
- request(args: PersonalSignMessageRequest): Promise;
- request(args: EIP712Request): Promise;
- request(args: { method: string; params?: Array }): Promise;
- disconnect?(): void;
-}
diff --git a/src/web3/index.ts b/src/web3/index.ts
deleted file mode 100644
index 9bd1857b..00000000
--- a/src/web3/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { useEthereumProvider } from './useEthereumProvider';
-export * from '../types/web3';
diff --git a/src/web3/useEthereumProvider.test.tsx b/src/web3/useEthereumProvider.test.tsx
deleted file mode 100644
index 6a4ea34f..00000000
--- a/src/web3/useEthereumProvider.test.tsx
+++ /dev/null
@@ -1,174 +0,0 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-
-import { EthereumOnboardingOptions, PlaidGlobalWithWeb3 } from '../types/web3';
-import { useEthereumProvider } from './useEthereumProvider';
-
-import useScript from 'react-script-hook';
-jest.mock('react-script-hook');
-const mockedUseScript = useScript as jest.Mock;
-
-const ScriptLoadingState = {
- LOADING: [true, null],
- LOADED: [false, null],
- ERROR: [false, 'SCRIPT_LOAD_ERROR'],
-};
-
-const ReadyState = {
- READY: 'READY',
- NOT_READY: 'NOT_READY',
- ERROR: 'ERROR',
- NO_ERROR: 'NO_ERROR',
- HAS_PROVIDER_ACTIVE: 'HAS_PROVIDER_ACTIVE',
- NO_PROVIDER_ACTIVE: 'NO_PROVIDER_ACTIVE',
-};
-
-const HookComponent: React.FC<{ config: EthereumOnboardingOptions }> = ({
- config,
-}) => {
- const { open, ready, error, isProviderActive } = useEthereumProvider(config);
- return (
-
-
-
{ready ? ReadyState.READY : ReadyState.NOT_READY}
-
{error ? ReadyState.ERROR : ReadyState.NO_ERROR}
-
- {isProviderActive != null
- ? ReadyState.HAS_PROVIDER_ACTIVE
- : ReadyState.NO_PROVIDER_ACTIVE}{' '}
-
-
- );
-};
-
-describe('useEthereumProvider', () => {
- const config: EthereumOnboardingOptions = {
- token: 'test-token',
- chain: {
- chainId: '0x1',
- rpcUrl: 'https://rpcurl.com',
- },
- onSuccess: jest.fn(),
- };
-
- beforeEach(() => {
- mockedUseScript.mockImplementation(() => ScriptLoadingState.LOADED);
- window.Plaid = {
- create: ({ onLoad }) => {
- onLoad && onLoad();
- return {
- create: jest.fn(),
- open: jest.fn(),
- exit: jest.fn(),
- destroy: jest.fn(),
- };
- },
- open: jest.fn(),
- exit: jest.fn(),
- destroy: jest.fn(),
- web3: jest.fn(() =>
- Promise.resolve({
- createEthereumOnboarding: jest.fn(),
- getCurrentEthereumProvider: jest.fn(),
- isProviderActive: jest.fn(),
- disconnectEthereumProvider: jest.fn(),
- })
- ),
- } as PlaidGlobalWithWeb3;
- });
-
- afterEach(() => {
- jest.restoreAllMocks();
- });
-
- it('should render with token', async () => {
- render();
- expect(screen.getByRole('button'));
- await screen.findByText(ReadyState.READY);
- await screen.findByText(ReadyState.HAS_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.NO_ERROR);
- });
-
- it('should not be ready when script is loading', async () => {
- mockedUseScript.mockImplementation(() => ScriptLoadingState.LOADING);
- render();
- await screen.findByText(ReadyState.NOT_READY);
- await screen.findByText(ReadyState.NO_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.NO_ERROR);
- });
-
- it('should not be ready if both token and publicKey are missing', async () => {
- render();
- await screen.findByText(ReadyState.NOT_READY);
- await screen.findByText(ReadyState.NO_ERROR);
- });
-
- it('should not be ready if script fails to load', async () => {
- const consoleSpy = jest
- .spyOn(console, 'error')
- .mockImplementationOnce(() => {});
- mockedUseScript.mockImplementation(() => ScriptLoadingState.ERROR);
-
- render();
- await screen.findByText(ReadyState.NOT_READY);
- await screen.findByText(ReadyState.NO_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.ERROR);
- expect(consoleSpy).toHaveBeenCalledWith(
- 'Error loading Plaid',
- 'SCRIPT_LOAD_ERROR'
- );
- });
-
- it('should be ready if token is generated async', async () => {
- const config: EthereumOnboardingOptions = {
- token: 'test-token',
- chain: {
- chainId: '0x1',
- rpcUrl: 'https://rpcurl.com',
- },
- onSuccess: jest.fn(),
- };
-
- const { rerender } = render(
-
- );
- await screen.findByText(ReadyState.NOT_READY);
- await screen.findByText(ReadyState.NO_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.NO_ERROR);
- config.token = 'test-token';
- rerender();
- await screen.findByText(ReadyState.READY);
- await screen.findByText(ReadyState.HAS_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.NO_ERROR);
- });
-
- it('should be ready if token is generated async and script loads after token', async () => {
- mockedUseScript.mockImplementation(() => ScriptLoadingState.LOADING);
-
- const c: EthereumOnboardingOptions = {
- token: null,
- chain: {
- chainId: '0x1',
- rpcUrl: 'https://rpcurl.com',
- },
- onSuccess: jest.fn(),
- };
- const { rerender } = render();
- await screen.findByText(ReadyState.NOT_READY);
- await screen.findByText(ReadyState.NO_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.NO_ERROR);
-
- c.token = 'test-token';
- rerender();
- await screen.findByText(ReadyState.NOT_READY);
- await screen.findByText(ReadyState.NO_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.NO_ERROR);
-
- mockedUseScript.mockImplementation(() => ScriptLoadingState.LOADED);
-
- rerender();
- await screen.findByText(ReadyState.READY);
- await screen.findByText(ReadyState.HAS_PROVIDER_ACTIVE);
- await screen.findByText(ReadyState.NO_ERROR);
- });
-});
diff --git a/src/web3/useEthereumProvider.ts b/src/web3/useEthereumProvider.ts
deleted file mode 100644
index 665420bc..00000000
--- a/src/web3/useEthereumProvider.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { useEffect, useState } from 'react';
-import useScript from 'react-script-hook';
-
-import { createWeb3Plaid, PlaidFactory } from '../factory';
-import {
- EthereumOnboardingOptions,
- PlaidWeb3,
- PlaidGlobalWithWeb3,
-} from '../types/web3';
-import { PLAID_LINK_STABLE_URL } from '../constants';
-
-const noop = () => {};
-
-export const useEthereumProvider = (options: EthereumOnboardingOptions) => {
- // Asynchronously load the plaid/link/stable url into the DOM
- const [loading, error] = useScript({
- src: PLAID_LINK_STABLE_URL,
- checkForExisting: true,
- });
-
- // internal state
- const [web3, setWeb3] = useState(null);
- const [plaid, setPlaid] = useState(null);
- const [iframeLoaded, setIframeLoaded] = useState(false);
-
- useEffect(() => {
- // If the link.js script is still loading, return prematurely
- if (loading) {
- return;
- }
-
- if (error || !window.Plaid) {
- // eslint-disable-next-line no-console
- console.error('Error loading Plaid', error);
- return;
- }
-
- if (!web3) {
- (window.Plaid as PlaidGlobalWithWeb3).web3().then(setWeb3);
- return;
- }
-
- // If the token is undefined, return prematurely
- if (!options.token) {
- return;
- }
-
- // if an old plaid instance exists, destroy it before
- // creating a new one
- if (plaid != null) {
- plaid.exit({ force: true }, () => plaid.destroy());
- }
-
- const next = createWeb3Plaid(
- {
- ...options,
- onLoad: () => {
- setIframeLoaded(true);
- options.onLoad && options.onLoad();
- },
- },
- web3.createEthereumOnboarding
- );
-
- setPlaid(next);
-
- // destroy the Plaid iframe factory
- return () => next.exit({ force: true }, () => next.destroy());
- }, [loading, error, options.token, web3, setWeb3]);
-
- const ready = plaid != null && (!loading || iframeLoaded) && web3 != null;
-
- const openNoOp = () => {
- if (!options.token) {
- console.warn(
- 'react-plaid-link: You cannot call open() without a valid token supplied to useEthereumProvider. This is a no-op.'
- );
- }
- };
-
- const returnValue = {
- error,
- ready,
- exit: plaid ? plaid.exit : noop,
- open: plaid ? plaid.open : openNoOp,
- getCurrentEthereumProvider:
- web3 && ready ? web3.getCurrentEthereumProvider : null,
- isProviderActive: web3 && ready ? web3.isProviderActive : null,
- disconnectEthereumProvider:
- web3 && ready ? web3.disconnectEthereumProvider : null,
- };
- return returnValue;
-};
diff --git a/stories/web3.tsx b/stories/web3.tsx
deleted file mode 100644
index 3c5dcbf6..00000000
--- a/stories/web3.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import React, { useCallback } from 'react';
-
-import { useEthereumProvider } from '../src/web3';
-
-const App = props => {
- const [addresses, setAddresses] = React.useState(undefined);
-
- const onSuccess = useCallback(
- async provider => {
- const accounts = await provider.request({ method: 'eth_accounts' });
- setAddresses(accounts);
- },
- [setAddresses]
- );
-
- const onExit = useCallback(
- (err, metadata) => console.log('onExit', err, metadata),
- []
- );
-
- const config = {
- token: props.token,
- chain: {
- chainId: '0x1',
- rpcUrl: 'https://rpc.com',
- },
- onSuccess,
- onExit,
- };
-
- const {
- open,
- ready,
- error,
- getCurrentEthereumProvider,
- } = useEthereumProvider(config);
-
- const checkProvider = useCallback(() => {
- if (!ready) {
- return;
- }
-
- (async () => {
- const provider = await getCurrentEthereumProvider(config.chain);
- if (provider) {
- const accounts = await provider.request({ method: 'eth_accounts' });
- setAddresses(accounts);
- }
- })();
- }, [ready, getCurrentEthereumProvider, setAddresses]);
-
- if (addresses) {
- return {addresses.join(', ')}
;
- }
-
- return (
- <>
-
-
- >
- );
-};
-
-export default App;