diff --git a/README.md b/README.md index 7bcd3896..d1fe8443 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ const tx = await erc20Deployer.deployJsonAbi( 'Token Name', // the name of the token '$tokenSymbol', // the symbol of the token - 1000000000000000000000000, // the total amount of the token (with 18 decimals; 1M = 1000000000000000000000000) + "1000000000000000000000000", // the total amount of the token (with 18 decimals; 1M = 1000000000000000000000000) await erc20Deployer.connection.getAddress() // the owner of the total amount of the tokens (your address) ); @@ -49,6 +49,7 @@ Please refer to the [`test/`](./test/models) folder to read further usage exampl ## Documentation * [Guides](https://docs.dappkit.dev/sdk-documentation/start-building/how-to-guides) +* [Advanced](./how-to/) * [SDK Documentation](https://sdk.dappkit.dev/) * [Use Cases](https://docs.dappkit.dev/sdk-documentation/use-cases) diff --git a/how-to/readme.md b/how-to/readme.md index 14f12ebf..6fb6d9a0 100644 --- a/how-to/readme.md +++ b/how-to/readme.md @@ -3,3 +3,4 @@ - [How to connect to EVM RPC?](./connect-to-blockchain.md) - [How to load custom ABI or contracts with dappkit?](./custom-abi.md) - [How to use @taikai/dappkit with your own Solidity project](./custom-project.md) +- [How to use Wallet Connect / Custom Provider](./use-wallet-connect.md); \ No newline at end of file diff --git a/how-to/use-wallet-connect.md b/how-to/use-wallet-connect.md new file mode 100644 index 00000000..ef24272d --- /dev/null +++ b/how-to/use-wallet-connect.md @@ -0,0 +1,33 @@ +# Wallet connect +@taikai/dappkit supports Wallet Connect (and any other web3 provider) via the `Web3ConnectionOptions.web3CustomProvider`. + +## Dependencies +```shell +$ npm install --save @taikai/dappkit @walletconnect/web3-provider +``` + +## Usage +```typescript +import WalletConnectProvider from "@walletconnect/web3-provider"; +import {Web3Connection} from "@taikai/dappkit"; + +// Create WalletConnect Provider +const provider = new WalletConnectProvider({ /* WalletConnect provider options go here */ }); + +// Enable session (triggers QR Code modal) +await provider.enable(); + +// Provide the custom provider to Web3Connection +const web3Connection = new Web3Connection({web3CustomProvider: provider}); + +// If `provider` was already connected when provided, then Web3Connection started itself; +// Otherwise you'll need to do that by hand, + +/* you only need to enable and start if you didn't enable before */ +// await provider.enable(); +// web3Connection.start(); +/* you only need to enable and start if you didn't enable before */ + +console.log('Connected address', await web3Connection.getAddress()) // Connected address: 0x1234... + +``` diff --git a/src/base/web3-connection.ts b/src/base/web3-connection.ts index e181a06c..b68d1a9b 100644 --- a/src/base/web3-connection.ts +++ b/src/base/web3-connection.ts @@ -1,6 +1,6 @@ import {Errors} from '@interfaces/error-enum'; import Web3 from 'web3'; -import {Account, HttpProvider, IpcProvider, WebsocketProvider} from 'web3-core'; +import {Account, provider as Provider} from 'web3-core'; import {HttpProviderOptions, WebsocketProviderOptions} from 'web3-core-helpers'; import {Web3ConnectionOptions} from '@interfaces/web3-connection-options'; import {Utils} from 'web3-utils'; @@ -10,7 +10,12 @@ export class Web3Connection { protected web3!: Web3; protected account!: Account; - constructor(readonly options: Web3ConnectionOptions) {} + constructor(readonly options: Web3ConnectionOptions) { + const {web3CustomProvider: provider = null} = options; + if (provider && typeof provider !== "string" && provider?.connected) { + this.start(); + } + } get started() { return !!this.web3; } get eth(): Eth { return this.web3?.eth; } @@ -68,23 +73,29 @@ export class Web3Connection { if (this.started && !restart) return; - const {web3Host = ``, web3ProviderOptions = undefined} = this.options; + const {web3Host = ``, web3ProviderOptions = undefined, web3CustomProvider = null} = this.options; + let provider: Provider = web3CustomProvider; - if (!web3Host) + if (!web3Host && !provider) throw new Error(Errors.MissingWeb3ProviderHost) - const web3Link = web3Host.toLowerCase(); - let provider: HttpProvider|IpcProvider|WebsocketProvider; + const web3Link = web3Host?.toLowerCase(); + + if (!provider) { + if (web3Link.includes(`http`)) + provider = new Web3.providers.HttpProvider(web3Link, web3ProviderOptions as HttpProviderOptions); + else if (web3Link.includes(`ws`)) + provider = new Web3.providers.WebsocketProvider(web3Link, web3ProviderOptions as WebsocketProviderOptions); + } - if (web3Link.includes(`http`)) - provider = new Web3.providers.HttpProvider(web3Link, web3ProviderOptions as HttpProviderOptions); - else if (web3Link.includes(`ws`)) - provider = new Web3.providers.WebsocketProvider(web3Link, web3ProviderOptions as WebsocketProviderOptions); - else { + if (!provider) { if (!this.options.web3ProviderOptions) throw new Error(Errors.ProviderOptionsAreMandatoryIfIPC); provider = new Web3.providers.IpcProvider(web3Link, web3ProviderOptions); } + + if (!provider) + throw new Error(Errors.FailedToAssignAProvider); this.web3 = new Web3(provider); if (!this.options.skipWindowAssignment && typeof window !== 'undefined') diff --git a/src/interfaces/error-enum.ts b/src/interfaces/error-enum.ts index dca50f73..b7f2a4e6 100644 --- a/src/interfaces/error-enum.ts +++ b/src/interfaces/error-enum.ts @@ -3,7 +3,7 @@ export enum Errors { ProviderOptionsAreMandatoryIfIPC = `Provider options are mandatory if chosen provider is IPC`, NoEthereumObjectFoundOnWindow = `No ethereum object found on window`, WindowObjectNotFound = `Window object not found`, - MissingWeb3ProviderHost = `Missing options.web3Host parameter`, + MissingWeb3ProviderHost = `Missing options.web3Host parameter and options.web3CustomProvider; Either is required.`, MissingAbiInterfaceFromArguments = `Missing ABI Interface from arguments list or empty Abi`, AmountNeedsToBeHigherThanZero = `Amount needs to be higher than zero`, MissingContractAddress = `Missing contract address`, @@ -22,4 +22,5 @@ export enum Errors { MissingEthUtilsAddressPleaseProvideOne = `Missing eth utils address, please provide one`, GasAndGasPriceMustBeProvidedIfNoAutoTxOptions = `Both gas and gasPrice must be provided if no auto txOptions`, MissingERC20UnderlyingToken = `Missing ERC20 underlying token address`, + FailedToAssignAProvider = `Failed to assign a provider. Doublecheck Web3ConnectionOptions.` } diff --git a/src/interfaces/web3-connection-options.ts b/src/interfaces/web3-connection-options.ts index 5a5c87a0..63fb78db 100644 --- a/src/interfaces/web3-connection-options.ts +++ b/src/interfaces/web3-connection-options.ts @@ -1,4 +1,5 @@ import {HttpProviderOptions, WebsocketProviderOptions} from 'web3-core-helpers'; +import {provider as Provider} from 'web3-core'; export interface Web3ConnectionOptions { /** @@ -16,6 +17,11 @@ export interface Web3ConnectionOptions { * @note you can provide a node server if you're using IPC */ web3ProviderOptions?: HttpProviderOptions | WebsocketProviderOptions; + + /** + * Pass a custom provider instead + */ + web3CustomProvider?: Provider; /** * Skip the assignment of `window.web3 = Web3`