@multiplatform.one/web3 7.17.0 → 7.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/dist/cjs/clients/adapter.cjs +33 -0
- package/dist/cjs/clients/adapter.native.js +36 -0
- package/dist/cjs/clients/adapter.native.js.map +1 -0
- package/dist/cjs/clients/bitcoin.cjs +46 -0
- package/dist/cjs/clients/bitcoin.native.js +51 -0
- package/dist/cjs/clients/bitcoin.native.js.map +1 -0
- package/dist/cjs/clients/connector.cjs +45 -0
- package/dist/cjs/clients/connector.native.js +49 -0
- package/dist/cjs/clients/connector.native.js.map +1 -0
- package/dist/cjs/clients/evm.cjs +171 -0
- package/dist/cjs/clients/evm.native.js +198 -0
- package/dist/cjs/clients/evm.native.js.map +1 -0
- package/dist/cjs/clients/gpg.cjs +31 -0
- package/dist/cjs/clients/gpg.native.js +34 -0
- package/dist/cjs/clients/gpg.native.js.map +1 -0
- package/dist/cjs/clients/hooks.cjs +78 -0
- package/dist/cjs/clients/hooks.native.js +85 -0
- package/dist/cjs/clients/hooks.native.js.map +1 -0
- package/dist/cjs/clients/index.cjs +49 -0
- package/dist/cjs/clients/index.native.js +52 -0
- package/dist/cjs/clients/index.native.js.map +1 -0
- package/dist/cjs/clients/solana.cjs +322 -0
- package/dist/cjs/clients/solana.native.js +511 -0
- package/dist/cjs/clients/solana.native.js.map +1 -0
- package/dist/cjs/clients/solanaMessage.cjs +38 -0
- package/dist/cjs/clients/solanaMessage.native.js +44 -0
- package/dist/cjs/clients/solanaMessage.native.js.map +1 -0
- package/dist/cjs/clients/sui.cjs +46 -0
- package/dist/cjs/clients/sui.native.js +51 -0
- package/dist/cjs/clients/sui.native.js.map +1 -0
- package/dist/cjs/clients/types.cjs +37 -0
- package/dist/cjs/clients/types.native.js +160 -0
- package/dist/cjs/clients/types.native.js.map +1 -0
- package/dist/cjs/clients/useSolanaClient.cjs +50 -0
- package/dist/cjs/clients/useSolanaClient.native.js +57 -0
- package/dist/cjs/clients/useSolanaClient.native.js.map +1 -0
- package/dist/cjs/clients/walletStandard.cjs +63 -0
- package/dist/cjs/clients/walletStandard.native.js +71 -0
- package/dist/cjs/clients/walletStandard.native.js.map +1 -0
- package/dist/cjs/connectkit/components/Common/ConnectorList/index.cjs +33 -5
- package/dist/cjs/connectkit/components/Common/ConnectorList/index.native.js +38 -5
- package/dist/cjs/connectkit/components/Common/ConnectorList/index.native.js.map +1 -1
- package/dist/cjs/connectkit/components/ConnectButton/index.cjs +5 -0
- package/dist/cjs/connectkit/components/ConnectButton/index.native.js +5 -0
- package/dist/cjs/connectkit/components/ConnectButton/index.native.js.map +1 -1
- package/dist/cjs/connectkit/components/ConnectModal/ConnectWithInjector/index.cjs +9 -4
- package/dist/cjs/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js +12 -7
- package/dist/cjs/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js.map +1 -1
- package/dist/cjs/connectkit/connectors/walletAdapterConnector.cjs +2 -0
- package/dist/cjs/connectkit/connectors/walletAdapterConnector.native.js +2 -0
- package/dist/cjs/connectkit/connectors/walletAdapterConnector.native.js.map +1 -1
- package/dist/cjs/connectkit/index.cjs +5 -0
- package/dist/cjs/connectkit/index.native.js +5 -0
- package/dist/cjs/connectkit/index.native.js.map +1 -1
- package/dist/cjs/connectkit/openConnector/context.cjs +146 -0
- package/dist/cjs/connectkit/openConnector/context.native.js +188 -0
- package/dist/cjs/connectkit/openConnector/context.native.js.map +1 -0
- package/dist/cjs/connectkit/openConnector/device.cjs +42 -0
- package/dist/cjs/connectkit/openConnector/device.native.js +51 -0
- package/dist/cjs/connectkit/openConnector/device.native.js.map +1 -0
- package/dist/cjs/connectkit/openConnector/index.cjs +35 -0
- package/dist/cjs/connectkit/openConnector/index.native.js +38 -0
- package/dist/cjs/connectkit/openConnector/index.native.js.map +1 -0
- package/dist/cjs/connectkit/openConnector/launcher.cjs +133 -0
- package/dist/cjs/connectkit/openConnector/launcher.native.js +158 -0
- package/dist/cjs/connectkit/openConnector/launcher.native.js.map +1 -0
- package/dist/cjs/connectkit/screens.cjs +1 -10
- package/dist/cjs/connectkit/screens.native.js +1 -12
- package/dist/cjs/connectkit/screens.native.js.map +1 -1
- package/dist/cjs/connectkit/siwe/SIWEProvider.cjs +4 -5
- package/dist/cjs/connectkit/siwe/SIWEProvider.native.js +4 -5
- package/dist/cjs/connectkit/siwe/SIWEProvider.native.js.map +1 -1
- package/dist/cjs/connectkit/siwe/connectIntent.cjs +9 -5
- package/dist/cjs/connectkit/siwe/connectIntent.native.js +10 -3
- package/dist/cjs/connectkit/siwe/connectIntent.native.js.map +1 -1
- package/dist/cjs/connectkit/useWeb3Modal.cjs +21 -0
- package/dist/cjs/connectkit/useWeb3Modal.native.js +22 -0
- package/dist/cjs/connectkit/useWeb3Modal.native.js.map +1 -1
- package/dist/cjs/connectkit/web3Bridge.cjs +4 -1
- package/dist/cjs/connectkit/web3Bridge.native.js +4 -1
- package/dist/cjs/connectkit/web3Bridge.native.js.map +1 -1
- package/dist/cjs/connectkit/web3Provider.native.js.map +1 -1
- package/dist/cjs/index.cjs +2 -1
- package/dist/cjs/index.native.js +1 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/solana.cjs +41 -0
- package/dist/cjs/solana.native.js +44 -0
- package/dist/cjs/solana.native.js.map +1 -0
- package/dist/esm/clients/adapter.mjs +8 -0
- package/dist/esm/clients/adapter.mjs.map +1 -0
- package/dist/esm/clients/adapter.native.js +8 -0
- package/dist/esm/clients/adapter.native.js.map +1 -0
- package/dist/esm/clients/bitcoin.mjs +21 -0
- package/dist/esm/clients/bitcoin.mjs.map +1 -0
- package/dist/esm/clients/bitcoin.native.js +23 -0
- package/dist/esm/clients/bitcoin.native.js.map +1 -0
- package/dist/esm/clients/connector.mjs +20 -0
- package/dist/esm/clients/connector.mjs.map +1 -0
- package/dist/esm/clients/connector.native.js +21 -0
- package/dist/esm/clients/connector.native.js.map +1 -0
- package/dist/esm/clients/evm.mjs +146 -0
- package/dist/esm/clients/evm.mjs.map +1 -0
- package/dist/esm/clients/evm.native.js +170 -0
- package/dist/esm/clients/evm.native.js.map +1 -0
- package/dist/esm/clients/gpg.mjs +3 -0
- package/dist/esm/clients/gpg.mjs.map +1 -0
- package/dist/esm/clients/gpg.native.js +3 -0
- package/dist/esm/clients/gpg.native.js.map +1 -0
- package/dist/esm/clients/hooks.mjs +51 -0
- package/dist/esm/clients/hooks.mjs.map +1 -0
- package/dist/esm/clients/hooks.native.js +55 -0
- package/dist/esm/clients/hooks.native.js.map +1 -0
- package/dist/esm/clients/index.mjs +11 -0
- package/dist/esm/clients/index.mjs.map +1 -0
- package/dist/esm/clients/index.native.js +11 -0
- package/dist/esm/clients/index.native.js.map +1 -0
- package/dist/esm/clients/solana.mjs +289 -0
- package/dist/esm/clients/solana.mjs.map +1 -0
- package/dist/esm/clients/solana.native.js +475 -0
- package/dist/esm/clients/solana.native.js.map +1 -0
- package/dist/esm/clients/solanaMessage.mjs +13 -0
- package/dist/esm/clients/solanaMessage.mjs.map +1 -0
- package/dist/esm/clients/solanaMessage.native.js +16 -0
- package/dist/esm/clients/solanaMessage.native.js.map +1 -0
- package/dist/esm/clients/sui.mjs +21 -0
- package/dist/esm/clients/sui.mjs.map +1 -0
- package/dist/esm/clients/sui.native.js +23 -0
- package/dist/esm/clients/sui.native.js.map +1 -0
- package/dist/esm/clients/types.mjs +12 -0
- package/dist/esm/clients/types.mjs.map +1 -0
- package/dist/esm/clients/types.native.js +132 -0
- package/dist/esm/clients/types.native.js.map +1 -0
- package/dist/esm/clients/useSolanaClient.mjs +25 -0
- package/dist/esm/clients/useSolanaClient.mjs.map +1 -0
- package/dist/esm/clients/useSolanaClient.native.js +29 -0
- package/dist/esm/clients/useSolanaClient.native.js.map +1 -0
- package/dist/esm/clients/walletStandard.mjs +33 -0
- package/dist/esm/clients/walletStandard.mjs.map +1 -0
- package/dist/esm/clients/walletStandard.native.js +38 -0
- package/dist/esm/clients/walletStandard.native.js.map +1 -0
- package/dist/esm/connectkit/components/Common/ConnectorList/index.mjs +34 -6
- package/dist/esm/connectkit/components/Common/ConnectorList/index.mjs.map +1 -1
- package/dist/esm/connectkit/components/Common/ConnectorList/index.native.js +39 -6
- package/dist/esm/connectkit/components/Common/ConnectorList/index.native.js.map +1 -1
- package/dist/esm/connectkit/components/ConnectButton/index.mjs +5 -0
- package/dist/esm/connectkit/components/ConnectButton/index.mjs.map +1 -1
- package/dist/esm/connectkit/components/ConnectButton/index.native.js +5 -0
- package/dist/esm/connectkit/components/ConnectButton/index.native.js.map +1 -1
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs +9 -4
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs.map +1 -1
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js +12 -7
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js.map +1 -1
- package/dist/esm/connectkit/connectors/walletAdapterConnector.mjs +2 -0
- package/dist/esm/connectkit/connectors/walletAdapterConnector.mjs.map +1 -1
- package/dist/esm/connectkit/connectors/walletAdapterConnector.native.js +2 -0
- package/dist/esm/connectkit/connectors/walletAdapterConnector.native.js.map +1 -1
- package/dist/esm/connectkit/index.mjs +3 -1
- package/dist/esm/connectkit/index.mjs.map +1 -1
- package/dist/esm/connectkit/index.native.js +3 -1
- package/dist/esm/connectkit/index.native.js.map +1 -1
- package/dist/esm/connectkit/openConnector/context.mjs +118 -0
- package/dist/esm/connectkit/openConnector/context.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/context.native.js +146 -0
- package/dist/esm/connectkit/openConnector/context.native.js.map +1 -0
- package/dist/esm/connectkit/openConnector/device.mjs +16 -0
- package/dist/esm/connectkit/openConnector/device.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/device.native.js +22 -0
- package/dist/esm/connectkit/openConnector/device.native.js.map +1 -0
- package/dist/esm/connectkit/openConnector/index.mjs +4 -0
- package/dist/esm/connectkit/openConnector/index.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/index.native.js +4 -0
- package/dist/esm/connectkit/openConnector/index.native.js.map +1 -0
- package/dist/esm/connectkit/openConnector/launcher.mjs +106 -0
- package/dist/esm/connectkit/openConnector/launcher.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/launcher.native.js +128 -0
- package/dist/esm/connectkit/openConnector/launcher.native.js.map +1 -0
- package/dist/esm/connectkit/screens.mjs +2 -11
- package/dist/esm/connectkit/screens.mjs.map +1 -1
- package/dist/esm/connectkit/screens.native.js +2 -13
- package/dist/esm/connectkit/screens.native.js.map +1 -1
- package/dist/esm/connectkit/siwe/SIWEProvider.mjs +4 -5
- package/dist/esm/connectkit/siwe/SIWEProvider.mjs.map +1 -1
- package/dist/esm/connectkit/siwe/SIWEProvider.native.js +4 -5
- package/dist/esm/connectkit/siwe/SIWEProvider.native.js.map +1 -1
- package/dist/esm/connectkit/siwe/connectIntent.mjs +9 -6
- package/dist/esm/connectkit/siwe/connectIntent.mjs.map +1 -1
- package/dist/esm/connectkit/siwe/connectIntent.native.js +10 -4
- package/dist/esm/connectkit/siwe/connectIntent.native.js.map +1 -1
- package/dist/esm/connectkit/useWeb3Modal.mjs +22 -1
- package/dist/esm/connectkit/useWeb3Modal.mjs.map +1 -1
- package/dist/esm/connectkit/useWeb3Modal.native.js +23 -1
- package/dist/esm/connectkit/useWeb3Modal.native.js.map +1 -1
- package/dist/esm/connectkit/web3Bridge.mjs +4 -1
- package/dist/esm/connectkit/web3Bridge.mjs.map +1 -1
- package/dist/esm/connectkit/web3Bridge.native.js +4 -1
- package/dist/esm/connectkit/web3Bridge.native.js.map +1 -1
- package/dist/esm/connectkit/web3Provider.mjs.map +1 -1
- package/dist/esm/connectkit/web3Provider.native.js.map +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +1 -0
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/solana.mjs +5 -0
- package/dist/esm/solana.mjs.map +1 -0
- package/dist/esm/solana.native.js +5 -0
- package/dist/esm/solana.native.js.map +1 -0
- package/dist/jsx/clients/adapter.mjs +8 -0
- package/dist/jsx/clients/adapter.mjs.map +1 -0
- package/dist/jsx/clients/adapter.native.js +36 -0
- package/dist/jsx/clients/adapter.native.js.map +1 -0
- package/dist/jsx/clients/bitcoin.mjs +21 -0
- package/dist/jsx/clients/bitcoin.mjs.map +1 -0
- package/dist/jsx/clients/bitcoin.native.js +51 -0
- package/dist/jsx/clients/bitcoin.native.js.map +1 -0
- package/dist/jsx/clients/connector.mjs +20 -0
- package/dist/jsx/clients/connector.mjs.map +1 -0
- package/dist/jsx/clients/connector.native.js +49 -0
- package/dist/jsx/clients/connector.native.js.map +1 -0
- package/dist/jsx/clients/evm.mjs +146 -0
- package/dist/jsx/clients/evm.mjs.map +1 -0
- package/dist/jsx/clients/evm.native.js +198 -0
- package/dist/jsx/clients/evm.native.js.map +1 -0
- package/dist/jsx/clients/gpg.mjs +3 -0
- package/dist/jsx/clients/gpg.mjs.map +1 -0
- package/dist/jsx/clients/gpg.native.js +34 -0
- package/dist/jsx/clients/gpg.native.js.map +1 -0
- package/dist/jsx/clients/hooks.mjs +51 -0
- package/dist/jsx/clients/hooks.mjs.map +1 -0
- package/dist/jsx/clients/hooks.native.js +85 -0
- package/dist/jsx/clients/hooks.native.js.map +1 -0
- package/dist/jsx/clients/index.mjs +11 -0
- package/dist/jsx/clients/index.mjs.map +1 -0
- package/dist/jsx/clients/index.native.js +52 -0
- package/dist/jsx/clients/index.native.js.map +1 -0
- package/dist/jsx/clients/solana.mjs +289 -0
- package/dist/jsx/clients/solana.mjs.map +1 -0
- package/dist/jsx/clients/solana.native.js +511 -0
- package/dist/jsx/clients/solana.native.js.map +1 -0
- package/dist/jsx/clients/solanaMessage.mjs +13 -0
- package/dist/jsx/clients/solanaMessage.mjs.map +1 -0
- package/dist/jsx/clients/solanaMessage.native.js +44 -0
- package/dist/jsx/clients/solanaMessage.native.js.map +1 -0
- package/dist/jsx/clients/sui.mjs +21 -0
- package/dist/jsx/clients/sui.mjs.map +1 -0
- package/dist/jsx/clients/sui.native.js +51 -0
- package/dist/jsx/clients/sui.native.js.map +1 -0
- package/dist/jsx/clients/types.mjs +12 -0
- package/dist/jsx/clients/types.mjs.map +1 -0
- package/dist/jsx/clients/types.native.js +160 -0
- package/dist/jsx/clients/types.native.js.map +1 -0
- package/dist/jsx/clients/useSolanaClient.mjs +25 -0
- package/dist/jsx/clients/useSolanaClient.mjs.map +1 -0
- package/dist/jsx/clients/useSolanaClient.native.js +57 -0
- package/dist/jsx/clients/useSolanaClient.native.js.map +1 -0
- package/dist/jsx/clients/walletStandard.mjs +33 -0
- package/dist/jsx/clients/walletStandard.mjs.map +1 -0
- package/dist/jsx/clients/walletStandard.native.js +71 -0
- package/dist/jsx/clients/walletStandard.native.js.map +1 -0
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.mjs +34 -6
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.mjs.map +1 -1
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.native.js +38 -5
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.native.js.map +1 -1
- package/dist/jsx/connectkit/components/ConnectButton/index.mjs +5 -0
- package/dist/jsx/connectkit/components/ConnectButton/index.mjs.map +1 -1
- package/dist/jsx/connectkit/components/ConnectButton/index.native.js +5 -0
- package/dist/jsx/connectkit/components/ConnectButton/index.native.js.map +1 -1
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs +9 -4
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs.map +1 -1
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js +12 -7
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js.map +1 -1
- package/dist/jsx/connectkit/connectors/walletAdapterConnector.mjs +2 -0
- package/dist/jsx/connectkit/connectors/walletAdapterConnector.mjs.map +1 -1
- package/dist/jsx/connectkit/connectors/walletAdapterConnector.native.js +2 -0
- package/dist/jsx/connectkit/connectors/walletAdapterConnector.native.js.map +1 -1
- package/dist/jsx/connectkit/index.mjs +3 -1
- package/dist/jsx/connectkit/index.mjs.map +1 -1
- package/dist/jsx/connectkit/index.native.js +5 -0
- package/dist/jsx/connectkit/index.native.js.map +1 -1
- package/dist/jsx/connectkit/openConnector/context.mjs +118 -0
- package/dist/jsx/connectkit/openConnector/context.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/context.native.js +188 -0
- package/dist/jsx/connectkit/openConnector/context.native.js.map +1 -0
- package/dist/jsx/connectkit/openConnector/device.mjs +16 -0
- package/dist/jsx/connectkit/openConnector/device.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/device.native.js +51 -0
- package/dist/jsx/connectkit/openConnector/device.native.js.map +1 -0
- package/dist/jsx/connectkit/openConnector/index.mjs +4 -0
- package/dist/jsx/connectkit/openConnector/index.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/index.native.js +38 -0
- package/dist/jsx/connectkit/openConnector/index.native.js.map +1 -0
- package/dist/jsx/connectkit/openConnector/launcher.mjs +106 -0
- package/dist/jsx/connectkit/openConnector/launcher.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/launcher.native.js +158 -0
- package/dist/jsx/connectkit/openConnector/launcher.native.js.map +1 -0
- package/dist/jsx/connectkit/screens.mjs +2 -11
- package/dist/jsx/connectkit/screens.mjs.map +1 -1
- package/dist/jsx/connectkit/screens.native.js +1 -12
- package/dist/jsx/connectkit/screens.native.js.map +1 -1
- package/dist/jsx/connectkit/siwe/SIWEProvider.mjs +4 -5
- package/dist/jsx/connectkit/siwe/SIWEProvider.mjs.map +1 -1
- package/dist/jsx/connectkit/siwe/SIWEProvider.native.js +4 -5
- package/dist/jsx/connectkit/siwe/SIWEProvider.native.js.map +1 -1
- package/dist/jsx/connectkit/siwe/connectIntent.mjs +9 -6
- package/dist/jsx/connectkit/siwe/connectIntent.mjs.map +1 -1
- package/dist/jsx/connectkit/siwe/connectIntent.native.js +10 -3
- package/dist/jsx/connectkit/siwe/connectIntent.native.js.map +1 -1
- package/dist/jsx/connectkit/useWeb3Modal.mjs +22 -1
- package/dist/jsx/connectkit/useWeb3Modal.mjs.map +1 -1
- package/dist/jsx/connectkit/useWeb3Modal.native.js +22 -0
- package/dist/jsx/connectkit/useWeb3Modal.native.js.map +1 -1
- package/dist/jsx/connectkit/web3Bridge.mjs +4 -1
- package/dist/jsx/connectkit/web3Bridge.mjs.map +1 -1
- package/dist/jsx/connectkit/web3Bridge.native.js +4 -1
- package/dist/jsx/connectkit/web3Bridge.native.js.map +1 -1
- package/dist/jsx/connectkit/web3Provider.mjs.map +1 -1
- package/dist/jsx/connectkit/web3Provider.native.js.map +1 -1
- package/dist/jsx/index.js +1 -0
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +1 -0
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +1 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/solana.mjs +5 -0
- package/dist/jsx/solana.mjs.map +1 -0
- package/dist/jsx/solana.native.js +44 -0
- package/dist/jsx/solana.native.js.map +1 -0
- package/package.json +14 -6
- package/src/clients/adapter.ts +13 -0
- package/src/clients/bitcoin.ts +42 -0
- package/src/clients/connector.spec.ts +78 -0
- package/src/clients/connector.ts +36 -0
- package/src/clients/evm.spec.ts +265 -0
- package/src/clients/evm.ts +223 -0
- package/src/clients/gpg.spec.ts +169 -0
- package/src/clients/gpg.ts +8 -0
- package/src/clients/hooks.spec.tsx +113 -0
- package/src/clients/hooks.ts +51 -0
- package/src/clients/index.ts +40 -0
- package/src/clients/solana.spec.ts +444 -0
- package/src/clients/solana.ts +465 -0
- package/src/clients/solanaMessage.ts +34 -0
- package/src/clients/sui.ts +42 -0
- package/src/clients/types.ts +40 -0
- package/src/clients/useSolanaClient.ts +31 -0
- package/src/clients/walletStandard.ts +87 -0
- package/src/connectkit/components/Common/ConnectorList/index.tsx +30 -2
- package/src/connectkit/components/ConnectButton/index.tsx +5 -0
- package/src/connectkit/components/ConnectModal/ConnectWithInjector/index.tsx +13 -8
- package/src/connectkit/connectors/walletAdapterConnector.ts +2 -0
- package/src/connectkit/index.ts +8 -0
- package/src/connectkit/openConnector/context.tsx +176 -0
- package/src/connectkit/openConnector/device.spec.ts +86 -0
- package/src/connectkit/openConnector/device.ts +37 -0
- package/src/connectkit/openConnector/index.ts +18 -0
- package/src/connectkit/openConnector/launcher.spec.ts +325 -0
- package/src/connectkit/openConnector/launcher.ts +203 -0
- package/src/connectkit/openConnector/modal.spec.tsx +330 -0
- package/src/connectkit/screens.tsx +2 -11
- package/src/connectkit/siwe/SIWEProvider.spec.tsx +112 -0
- package/src/connectkit/siwe/SIWEProvider.tsx +6 -10
- package/src/connectkit/siwe/connectIntent.spec.ts +90 -0
- package/src/connectkit/siwe/connectIntent.ts +19 -6
- package/src/connectkit/useWeb3Modal.ts +25 -1
- package/src/connectkit/web3Bridge.tsx +4 -1
- package/src/connectkit/web3Provider.tsx +4 -1
- package/src/index.ts +4 -0
- package/src/solana.ts +30 -0
- package/types/clients/adapter.d.ts +5 -0
- package/types/clients/adapter.d.ts.map +1 -0
- package/types/clients/bitcoin.d.ts +21 -0
- package/types/clients/bitcoin.d.ts.map +1 -0
- package/types/clients/connector.d.ts +14 -0
- package/types/clients/connector.d.ts.map +1 -0
- package/types/clients/evm.d.ts +68 -0
- package/types/clients/evm.d.ts.map +1 -0
- package/types/clients/gpg.d.ts +2 -0
- package/types/clients/gpg.d.ts.map +1 -0
- package/types/clients/hooks.d.ts +16 -0
- package/types/clients/hooks.d.ts.map +1 -0
- package/types/clients/index.d.ts +10 -0
- package/types/clients/index.d.ts.map +1 -0
- package/types/clients/solana.d.ts +111 -0
- package/types/clients/solana.d.ts.map +1 -0
- package/types/clients/solanaMessage.d.ts +18 -0
- package/types/clients/solanaMessage.d.ts.map +1 -0
- package/types/clients/sui.d.ts +21 -0
- package/types/clients/sui.d.ts.map +1 -0
- package/types/clients/types.d.ts +27 -0
- package/types/clients/types.d.ts.map +1 -0
- package/types/clients/useSolanaClient.d.ts +11 -0
- package/types/clients/useSolanaClient.d.ts.map +1 -0
- package/types/clients/walletStandard.d.ts +63 -0
- package/types/clients/walletStandard.d.ts.map +1 -0
- package/types/connectkit/components/Common/ConnectorList/index.d.ts.map +1 -1
- package/types/connectkit/components/ConnectButton/index.d.ts.map +1 -1
- package/types/connectkit/components/ConnectModal/ConnectWithInjector/index.d.ts.map +1 -1
- package/types/connectkit/connectors/walletAdapterConnector.d.ts.map +1 -1
- package/types/connectkit/index.d.ts +2 -0
- package/types/connectkit/index.d.ts.map +1 -1
- package/types/connectkit/openConnector/context.d.ts +48 -0
- package/types/connectkit/openConnector/context.d.ts.map +1 -0
- package/types/connectkit/openConnector/device.d.ts +18 -0
- package/types/connectkit/openConnector/device.d.ts.map +1 -0
- package/types/connectkit/openConnector/index.d.ts +3 -0
- package/types/connectkit/openConnector/index.d.ts.map +1 -0
- package/types/connectkit/openConnector/launcher.d.ts +64 -0
- package/types/connectkit/openConnector/launcher.d.ts.map +1 -0
- package/types/connectkit/screens.d.ts.map +1 -1
- package/types/connectkit/siwe/SIWEProvider.d.ts.map +1 -1
- package/types/connectkit/siwe/connectIntent.d.ts +8 -3
- package/types/connectkit/siwe/connectIntent.d.ts.map +1 -1
- package/types/connectkit/useWeb3Modal.d.ts +16 -0
- package/types/connectkit/useWeb3Modal.d.ts.map +1 -1
- package/types/connectkit/web3Bridge.d.ts.map +1 -1
- package/types/connectkit/web3Provider.d.ts +4 -1
- package/types/connectkit/web3Provider.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/solana.d.ts +4 -0
- package/types/solana.d.ts.map +1 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Minimal Wallet Standard plumbing for Solana: the registry handshake and the
|
|
2
|
+
// feature shapes the client calls. Structural types instead of @wallet-standard/*
|
|
3
|
+
// so the page bundle carries no extra package; Phantom, Solflare and Backpack all
|
|
4
|
+
// register this way.
|
|
5
|
+
|
|
6
|
+
export interface StandardWalletAccount {
|
|
7
|
+
readonly address: string;
|
|
8
|
+
readonly publicKey: Uint8Array;
|
|
9
|
+
readonly chains: readonly string[];
|
|
10
|
+
readonly features: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface StandardWallet {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly icon?: string;
|
|
16
|
+
readonly chains: readonly string[];
|
|
17
|
+
readonly accounts: readonly StandardWalletAccount[];
|
|
18
|
+
readonly features: Readonly<Record<string, unknown>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const SolanaSignMessage = "solana:signMessage";
|
|
22
|
+
export const SolanaSignTransaction = "solana:signTransaction";
|
|
23
|
+
export const SolanaSignAndSendTransaction = "solana:signAndSendTransaction";
|
|
24
|
+
export const StandardConnect = "standard:connect";
|
|
25
|
+
|
|
26
|
+
export interface SolanaSignMessageFeature {
|
|
27
|
+
signMessage(
|
|
28
|
+
...inputs: { account: StandardWalletAccount; message: Uint8Array }[]
|
|
29
|
+
): Promise<{ signedMessage: Uint8Array; signature: Uint8Array }[]>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface SolanaSignTransactionFeature {
|
|
33
|
+
signTransaction(
|
|
34
|
+
...inputs: { account: StandardWalletAccount; transaction: Uint8Array; chain?: string }[]
|
|
35
|
+
): Promise<{ signedTransaction: Uint8Array }[]>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface SolanaSignAndSendTransactionFeature {
|
|
39
|
+
signAndSendTransaction(
|
|
40
|
+
...inputs: {
|
|
41
|
+
account: StandardWalletAccount;
|
|
42
|
+
transaction: Uint8Array;
|
|
43
|
+
chain: string;
|
|
44
|
+
options?: { commitment?: "processed" | "confirmed" | "finalized"; skipPreflight?: boolean };
|
|
45
|
+
}[]
|
|
46
|
+
): Promise<{ signature: Uint8Array }[]>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface StandardConnectFeature {
|
|
50
|
+
connect(input?: { silent?: boolean }): Promise<{ accounts: readonly StandardWalletAccount[] }>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Every wallet registered with the Wallet Standard right now. Wallets answer
|
|
55
|
+
* `app-ready` synchronously, so this can be called again to pick up late ones.
|
|
56
|
+
*/
|
|
57
|
+
export function getStandardWallets(): StandardWallet[] {
|
|
58
|
+
if (typeof window === "undefined") return [];
|
|
59
|
+
const wallets: StandardWallet[] = [];
|
|
60
|
+
const api = {
|
|
61
|
+
register: (...registered: StandardWallet[]) => {
|
|
62
|
+
wallets.push(...registered);
|
|
63
|
+
return () => {};
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
const onRegister = (event: Event) => {
|
|
67
|
+
try {
|
|
68
|
+
((event as CustomEvent).detail as (a: typeof api) => void)(api);
|
|
69
|
+
} catch {
|
|
70
|
+
// a wallet that throws during registration is simply not offered
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
window.addEventListener("wallet-standard:register-wallet", onRegister);
|
|
74
|
+
try {
|
|
75
|
+
window.dispatchEvent(new CustomEvent("wallet-standard:app-ready", { detail: api }));
|
|
76
|
+
} finally {
|
|
77
|
+
window.removeEventListener("wallet-standard:register-wallet", onRegister);
|
|
78
|
+
}
|
|
79
|
+
return [...new Set(wallets)];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Wallets that can sign Solana transactions. */
|
|
83
|
+
export function getSolanaWallets(): StandardWallet[] {
|
|
84
|
+
return getStandardWallets().filter(
|
|
85
|
+
(wallet) => wallet.features[SolanaSignTransaction] && wallet.features[StandardConnect],
|
|
86
|
+
);
|
|
87
|
+
}
|
|
@@ -10,6 +10,11 @@ import {
|
|
|
10
10
|
isMetaMaskConnector,
|
|
11
11
|
isPortoConnector,
|
|
12
12
|
isWalletConnectConnector,
|
|
13
|
+
resolveListEntries,
|
|
14
|
+
useModalState,
|
|
15
|
+
useScreenRegistry,
|
|
16
|
+
type ScreenDef,
|
|
17
|
+
type ScreenListEntry,
|
|
13
18
|
} from "@multiplatform.one/connectkit";
|
|
14
19
|
|
|
15
20
|
import {
|
|
@@ -51,6 +56,9 @@ const ConnectorList = () => {
|
|
|
51
56
|
const { lastConnectorId } = useLastConnector();
|
|
52
57
|
const aaveAccountConnector = useAaveAccountConnector();
|
|
53
58
|
const [expanded, setExpanded] = useState<string | null>(null);
|
|
59
|
+
const { screens } = useScreenRegistry();
|
|
60
|
+
const modalState = useModalState();
|
|
61
|
+
const screenEntries = resolveListEntries(screens, modalState);
|
|
54
62
|
|
|
55
63
|
const filteredWallets = wallets.filter((wallet) => wallet.id !== aaveAccountConnector?.id);
|
|
56
64
|
|
|
@@ -79,7 +87,7 @@ const ConnectorList = () => {
|
|
|
79
87
|
}
|
|
80
88
|
}
|
|
81
89
|
|
|
82
|
-
if (groups.length === 0) {
|
|
90
|
+
if (groups.length === 0 && screenEntries.length === 0) {
|
|
83
91
|
return (
|
|
84
92
|
<ScrollArea mobileDirection={"horizontal"}>
|
|
85
93
|
<Alert error>No connectors found in ConnectKit config.</Alert>
|
|
@@ -111,7 +119,7 @@ const ConnectorList = () => {
|
|
|
111
119
|
|
|
112
120
|
return (
|
|
113
121
|
<ScrollArea mobileDirection={"horizontal"}>
|
|
114
|
-
<ConnectorsContainer $mobile={isMobile} $totalResults={groups.length}>
|
|
122
|
+
<ConnectorsContainer $mobile={isMobile} $totalResults={groups.length + screenEntries.length}>
|
|
115
123
|
{groups.map((group) =>
|
|
116
124
|
group.members.length === 1 ? (
|
|
117
125
|
<ConnectorItem
|
|
@@ -128,6 +136,9 @@ const ConnectorList = () => {
|
|
|
128
136
|
/>
|
|
129
137
|
),
|
|
130
138
|
)}
|
|
139
|
+
{screenEntries.map((def) => (
|
|
140
|
+
<ScreenEntryItem key={def.id} def={def} />
|
|
141
|
+
))}
|
|
131
142
|
</ConnectorsContainer>
|
|
132
143
|
</ScrollArea>
|
|
133
144
|
);
|
|
@@ -135,6 +146,23 @@ const ConnectorList = () => {
|
|
|
135
146
|
|
|
136
147
|
export default ConnectorList;
|
|
137
148
|
|
|
149
|
+
// A registered screen offered in the list (GPG): tapping it routes to the screen.
|
|
150
|
+
const ScreenEntryItem = ({ def }: { def: ScreenDef & { listEntry: ScreenListEntry } }) => {
|
|
151
|
+
const context = useContext();
|
|
152
|
+
const { name, icon } = def.listEntry;
|
|
153
|
+
return (
|
|
154
|
+
<ConnectorButton
|
|
155
|
+
type="button"
|
|
156
|
+
data-screen-entry={def.id}
|
|
157
|
+
disabled={context.route !== routes.CONNECTORS}
|
|
158
|
+
onClick={() => context.setRoute(def.id)}
|
|
159
|
+
>
|
|
160
|
+
<ConnectorIcon data-shape="squircle">{icon}</ConnectorIcon>
|
|
161
|
+
<ConnectorLabel>{name}</ConnectorLabel>
|
|
162
|
+
</ConnectorButton>
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
138
166
|
// A collapsed multi-chain wallet row — clicking expands the chain picker.
|
|
139
167
|
const GroupItem = ({
|
|
140
168
|
group,
|
|
@@ -25,6 +25,7 @@ import { useSIWE } from "../../siwe";
|
|
|
25
25
|
import { Chain } from "viem";
|
|
26
26
|
import { useChainIsSupported } from "../../hooks/useChainIsSupported";
|
|
27
27
|
import { useEnsFallbackConfig } from "../../hooks/useEnsFallbackConfig";
|
|
28
|
+
import { useConnectorLauncher } from "../../openConnector";
|
|
28
29
|
|
|
29
30
|
const contentVariants: Variants = {
|
|
30
31
|
initial: {
|
|
@@ -123,6 +124,7 @@ const ConnectButtonRenderer: React.FC<ConnectButtonRendererProps> = ({ children
|
|
|
123
124
|
const isMounted = useIsMounted();
|
|
124
125
|
const context = useContext();
|
|
125
126
|
const { open, setOpen } = useModal();
|
|
127
|
+
const launcher = useConnectorLauncher();
|
|
126
128
|
|
|
127
129
|
const { address, isConnected, chain } = useAccount();
|
|
128
130
|
const isChainSupported = useChainIsSupported(chain?.id);
|
|
@@ -139,6 +141,7 @@ const ConnectButtonRenderer: React.FC<ConnectButtonRendererProps> = ({ children
|
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
function show() {
|
|
144
|
+
if (!isConnected && launcher?.openPreferredConnector()) return;
|
|
142
145
|
setOpen(true);
|
|
143
146
|
context.setRoute(isConnected ? routes.PROFILE : routes.CONNECTORS);
|
|
144
147
|
}
|
|
@@ -336,11 +339,13 @@ export function ConnectKitButton({
|
|
|
336
339
|
const isMounted = useIsMounted();
|
|
337
340
|
|
|
338
341
|
const context = useContext();
|
|
342
|
+
const launcher = useConnectorLauncher();
|
|
339
343
|
|
|
340
344
|
const { isConnected, address, chain } = useAccount();
|
|
341
345
|
const chainIsSupported = useChainIsSupported(chain?.id);
|
|
342
346
|
|
|
343
347
|
function show() {
|
|
348
|
+
if (!isConnected && launcher?.openPreferredConnector()) return;
|
|
344
349
|
context.setOpen(true);
|
|
345
350
|
context.setRoute(isConnected ? routes.PROFILE : routes.CONNECTORS);
|
|
346
351
|
}
|
|
@@ -38,6 +38,7 @@ import { useConnect } from "../../../hooks/useConnect";
|
|
|
38
38
|
import { useWallet } from "../../../wallets/useWallets";
|
|
39
39
|
import { setConnectIntent } from "../../../siwe/connectIntent";
|
|
40
40
|
import { isEmbeddedDesktopWebview } from "../../../connectors/embeddedDesktop";
|
|
41
|
+
import { useConnectorLauncher } from "../../../openConnector";
|
|
41
42
|
import CircleSpinner from "./CircleSpinner";
|
|
42
43
|
|
|
43
44
|
export const states = {
|
|
@@ -166,6 +167,12 @@ const ConnectWithInjector: React.FC<{
|
|
|
166
167
|
};
|
|
167
168
|
}, [wallet?.connector]);
|
|
168
169
|
|
|
170
|
+
// openConnector fires connect() inside the app's own tap, before this screen
|
|
171
|
+
// mounts, so the connector may have announced its deeplink already.
|
|
172
|
+
const launcher = useConnectorLauncher();
|
|
173
|
+
const launchedHere = !!wallet && launcher?.pending?.connector.uid === wallet.connector.uid;
|
|
174
|
+
const deeplink = sdkDeeplink ?? (launchedHere ? launcher?.pendingDeeplink : null) ?? undefined;
|
|
175
|
+
|
|
169
176
|
const expiryDefault = 9; // Starting at 10 causes layout shifting, better to start at 9
|
|
170
177
|
const [expiryTimer, setExpiryTimer] = useState<number>(expiryDefault);
|
|
171
178
|
|
|
@@ -176,7 +183,7 @@ const ConnectWithInjector: React.FC<{
|
|
|
176
183
|
const showEmbeddedDesktopMetaMaskQr =
|
|
177
184
|
!isMobile &&
|
|
178
185
|
isMetaMaskConnector(wallet?.connector.id) &&
|
|
179
|
-
!!
|
|
186
|
+
!!deeplink &&
|
|
180
187
|
isEmbeddedDesktopWebview();
|
|
181
188
|
|
|
182
189
|
const extensionUrl = wallet?.downloadUrls?.[browser];
|
|
@@ -221,6 +228,8 @@ const ConnectWithInjector: React.FC<{
|
|
|
221
228
|
// (ConnectorList shouldConnectImmediately); firing again here would queue a
|
|
222
229
|
// second SDK request / deeplink into the MetaMask app.
|
|
223
230
|
if (isMobile && isMetaMaskConnector(wallet?.connector.id)) return;
|
|
231
|
+
// Same when openConnector already fired it inside the app's tap.
|
|
232
|
+
if (launchedHere) return;
|
|
224
233
|
|
|
225
234
|
// UX: Give user time to see the UI before opening the extension
|
|
226
235
|
connectTimeout = setTimeout(runConnect, 600);
|
|
@@ -468,11 +477,7 @@ const ConnectWithInjector: React.FC<{
|
|
|
468
477
|
)}
|
|
469
478
|
</ModalContent>
|
|
470
479
|
{showEmbeddedDesktopMetaMaskQr && (
|
|
471
|
-
<CustomQRCode
|
|
472
|
-
value={sdkDeeplink}
|
|
473
|
-
image={walletInfo.icon}
|
|
474
|
-
imagePosition="center"
|
|
475
|
-
/>
|
|
480
|
+
<CustomQRCode value={deeplink} image={walletInfo.icon} imagePosition="center" />
|
|
476
481
|
)}
|
|
477
482
|
{/* The SDK auto-opens its deeplink, but browsers drop external-
|
|
478
483
|
protocol navigations whose user activation expired while the
|
|
@@ -485,8 +490,8 @@ const ConnectWithInjector: React.FC<{
|
|
|
485
490
|
ASWebAuthenticationSession). So once the SDK emits
|
|
486
491
|
display_uri we render it as a REAL anchor — same-tab,
|
|
487
492
|
because auth sheets can't open new tabs. */}
|
|
488
|
-
{isMobile && isMetaMaskConnector(wallet?.connector.id) &&
|
|
489
|
-
<Button href={
|
|
493
|
+
{isMobile && isMetaMaskConnector(wallet?.connector.id) && deeplink && (
|
|
494
|
+
<Button href={deeplink} target="_self">
|
|
490
495
|
Open {walletInfo.name}
|
|
491
496
|
</Button>
|
|
492
497
|
)}
|
|
@@ -71,6 +71,8 @@ export function walletAdapterConnector(entry: WalletConnectorEntry) {
|
|
|
71
71
|
icon: entry.icon,
|
|
72
72
|
// custom tag read by getConnectorEcosystem()/WalletProps.ecosystem
|
|
73
73
|
ecosystem: entry.ecosystem,
|
|
74
|
+
// read by clientForConnector() to build the per-chain client
|
|
75
|
+
adapter: entry.adapter,
|
|
74
76
|
|
|
75
77
|
async getProvider() {
|
|
76
78
|
return provider;
|
package/src/connectkit/index.ts
CHANGED
|
@@ -8,6 +8,14 @@ export { wallets } from "./wallets";
|
|
|
8
8
|
// web3's wrapper (generic connectkit useModal + wallet/SIWE openers) keeps the
|
|
9
9
|
// consumer-facing `useModal` API. The agnostic base lives in ./hooks/useModal.
|
|
10
10
|
export { useWeb3Modal as useModal } from "./useWeb3Modal";
|
|
11
|
+
export {
|
|
12
|
+
DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS,
|
|
13
|
+
DEFAULT_OPEN_CONNECTOR_FALLBACK_MS,
|
|
14
|
+
type MobileConnectOptions,
|
|
15
|
+
type OpenConnectorOptions,
|
|
16
|
+
type Web3ConnectKitOptions,
|
|
17
|
+
} from "./openConnector";
|
|
18
|
+
export { CONNECT_INTENT_TTL_MS } from "./siwe/connectIntent";
|
|
11
19
|
export { SIWEProvider, useSIWE, SIWE_NONCE_QUERY_KEY, SIWE_SESSION_QUERY_KEY } from "./siwe";
|
|
12
20
|
export type { SIWESession, SIWEConfig } from "./siwe";
|
|
13
21
|
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext as useReactContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
useSyncExternalStore,
|
|
9
|
+
} from "react";
|
|
10
|
+
import { useAccountEffect, type Connector } from "wagmi";
|
|
11
|
+
import {
|
|
12
|
+
routes,
|
|
13
|
+
useContext,
|
|
14
|
+
isMobile,
|
|
15
|
+
type ConnectKitOptions,
|
|
16
|
+
} from "@multiplatform.one/connectkit";
|
|
17
|
+
|
|
18
|
+
import { useConnect } from "../hooks/useConnect";
|
|
19
|
+
import { useConnectors } from "../hooks/useConnectors";
|
|
20
|
+
import { useWallets, type WalletProps } from "../wallets/useWallets";
|
|
21
|
+
import { clearConnectIntent, setConnectIntent } from "../siwe/connectIntent";
|
|
22
|
+
import { defaultOpenConnectorFallbackMs } from "./device";
|
|
23
|
+
import {
|
|
24
|
+
createConnectorLauncher,
|
|
25
|
+
type LauncherDeps,
|
|
26
|
+
type OpenConnectorOptions,
|
|
27
|
+
type PendingConnect,
|
|
28
|
+
} from "./launcher";
|
|
29
|
+
|
|
30
|
+
export type MobileConnectOptions = {
|
|
31
|
+
/**
|
|
32
|
+
* Connector id a phone connects straight to (e.g. `"metaMaskSDK"`): `openSIWE()`
|
|
33
|
+
* and the default ConnectKit button skip the wallet list for it. Desktop keeps
|
|
34
|
+
* the list. A phone here is what connectkit's `isMobile()` reads from the user
|
|
35
|
+
* agent, so iPadOS Safari and Android's "Desktop site", which both send a desktop
|
|
36
|
+
* one, keep the list too.
|
|
37
|
+
*/
|
|
38
|
+
preferredConnector?: string;
|
|
39
|
+
/** Passed to `openConnector` for the preferred connector. */
|
|
40
|
+
fallbackMs?: number;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** ConnectKit options as web3's ConnectKitProvider takes them. */
|
|
44
|
+
export type Web3ConnectKitOptions = ConnectKitOptions & {
|
|
45
|
+
mobile?: MobileConnectOptions;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type ConnectorLauncherValue = {
|
|
49
|
+
openConnector: (id: string, options?: OpenConnectorOptions) => void;
|
|
50
|
+
/**
|
|
51
|
+
* On a phone with `mobile.preferredConnector` set, open that connector and
|
|
52
|
+
* return true. Otherwise do nothing and return false.
|
|
53
|
+
*/
|
|
54
|
+
openPreferredConnector: () => boolean;
|
|
55
|
+
/** Wallet id `openConnector` is connecting, or null. */
|
|
56
|
+
pendingConnector: string | null;
|
|
57
|
+
/** The pending connect's wallet deeplink, once the connector announced it. */
|
|
58
|
+
pendingDeeplink: string | null;
|
|
59
|
+
/** The pending connect, for screens that must not start a second one. */
|
|
60
|
+
pending: PendingConnect | null;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const ConnectorLauncherContext = createContext<ConnectorLauncherValue | null>(null);
|
|
64
|
+
|
|
65
|
+
/** The launcher, or null outside web3's ConnectKitProvider. */
|
|
66
|
+
export function useConnectorLauncher(): ConnectorLauncherValue | null {
|
|
67
|
+
return useReactContext(ConnectorLauncherContext);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function getMobileOptions(options?: ConnectKitOptions): MobileConnectOptions {
|
|
71
|
+
return (options as Web3ConnectKitOptions | undefined)?.mobile ?? {};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Find the list wallet for a connector id. The list hides the MetaMask SDK row
|
|
76
|
+
* behind an injected MetaMask (EIP-6963 `io.metamask`), so an id that is not in
|
|
77
|
+
* the list resolves through its connector's rdns.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveWallet(
|
|
80
|
+
wallets: readonly WalletProps[],
|
|
81
|
+
connectors: readonly Connector[],
|
|
82
|
+
id: string,
|
|
83
|
+
): WalletProps | undefined {
|
|
84
|
+
const direct = wallets.find((wallet) => wallet.id === id);
|
|
85
|
+
if (direct) return direct;
|
|
86
|
+
const connector = connectors.find((c) => c.id === id);
|
|
87
|
+
if (!connector) return undefined;
|
|
88
|
+
const rdns = connector.rdns === undefined ? [] : [connector.rdns].flat();
|
|
89
|
+
return wallets.find((wallet) => rdns.includes(wallet.id));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const ConnectorLauncherProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
93
|
+
children,
|
|
94
|
+
}) => {
|
|
95
|
+
const context = useContext();
|
|
96
|
+
const wallets = useWallets();
|
|
97
|
+
const { connectAsync } = useConnect();
|
|
98
|
+
const connectors = useConnectors();
|
|
99
|
+
|
|
100
|
+
const depsRef = useRef<LauncherDeps>(null as unknown as LauncherDeps);
|
|
101
|
+
depsRef.current = {
|
|
102
|
+
connect: (connector) => connectAsync({ connector }),
|
|
103
|
+
showConnecting: (walletId) => {
|
|
104
|
+
context.setConnector({ id: walletId });
|
|
105
|
+
context.setRoute(routes.CONNECT);
|
|
106
|
+
context.setOpen(true);
|
|
107
|
+
},
|
|
108
|
+
showList: () => {
|
|
109
|
+
context.setRoute(routes.CONNECTORS);
|
|
110
|
+
context.setOpen(true);
|
|
111
|
+
},
|
|
112
|
+
onFailed: () => clearConnectIntent(),
|
|
113
|
+
};
|
|
114
|
+
const latest = useRef({ wallets, connectors, options: context.options });
|
|
115
|
+
latest.current = { wallets, connectors, options: context.options };
|
|
116
|
+
|
|
117
|
+
const launcher = useMemo(() => createConnectorLauncher(() => depsRef.current), []);
|
|
118
|
+
useEffect(() => () => launcher.cancel(), [launcher]);
|
|
119
|
+
const pending = useSyncExternalStore(launcher.subscribe, launcher.pending, launcher.pending);
|
|
120
|
+
|
|
121
|
+
// The session belongs to the connecting screen it opened. Once the user closes the
|
|
122
|
+
// modal or moves off that screen, a fallback must not pull the list back up.
|
|
123
|
+
const { open, route } = context;
|
|
124
|
+
const shownId = context.connector?.id;
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (!pending) return;
|
|
127
|
+
if (!open || route !== routes.CONNECT || shownId !== pending.walletId) launcher.cancel();
|
|
128
|
+
}, [launcher, pending, open, route, shownId]);
|
|
129
|
+
|
|
130
|
+
// Any wallet connecting ends the session, including one the user connected some
|
|
131
|
+
// other way while this connect never answered.
|
|
132
|
+
useAccountEffect({ onConnect: () => launcher.cancel() });
|
|
133
|
+
|
|
134
|
+
const openConnector = useCallback(
|
|
135
|
+
(id: string, options: OpenConnectorOptions = {}) => {
|
|
136
|
+
const { wallets, connectors } = latest.current;
|
|
137
|
+
const wallet = resolveWallet(wallets, connectors, id);
|
|
138
|
+
if (!wallet) {
|
|
139
|
+
context.log(`openConnector: no connector ${id}, showing the wallet list.`);
|
|
140
|
+
depsRef.current.showList();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// A phone bounces out to the wallet app and often reloads this page on the
|
|
144
|
+
// way back; the intent is what carries the flow on into signing.
|
|
145
|
+
setConnectIntent();
|
|
146
|
+
launcher.open(wallet.id, wallet.connector, {
|
|
147
|
+
fallbackMs: options.fallbackMs ?? defaultOpenConnectorFallbackMs(),
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
// context.log is stable enough for a debug line; the rest is read through refs.
|
|
151
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
152
|
+
[launcher],
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const openPreferredConnector = useCallback(() => {
|
|
156
|
+
const mobile = getMobileOptions(latest.current.options);
|
|
157
|
+
if (!mobile.preferredConnector || !isMobile()) return false;
|
|
158
|
+
openConnector(mobile.preferredConnector, { fallbackMs: mobile.fallbackMs });
|
|
159
|
+
return true;
|
|
160
|
+
}, [openConnector]);
|
|
161
|
+
|
|
162
|
+
const value = useMemo<ConnectorLauncherValue>(
|
|
163
|
+
() => ({
|
|
164
|
+
openConnector,
|
|
165
|
+
openPreferredConnector,
|
|
166
|
+
pendingConnector: pending?.walletId ?? null,
|
|
167
|
+
pendingDeeplink: pending?.deeplink ?? null,
|
|
168
|
+
pending,
|
|
169
|
+
}),
|
|
170
|
+
[openConnector, openPreferredConnector, pending],
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<ConnectorLauncherContext.Provider value={value}>{children}</ConnectorLauncherContext.Provider>
|
|
175
|
+
);
|
|
176
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { defaultOpenConnectorFallbackMs, isTouchDevice } from "./device";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS,
|
|
7
|
+
DEFAULT_OPEN_CONNECTOR_FALLBACK_MS,
|
|
8
|
+
} from "./launcher";
|
|
9
|
+
|
|
10
|
+
const IPADOS_SAFARI_UA =
|
|
11
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15";
|
|
12
|
+
const ANDROID_DESKTOP_SITE_UA =
|
|
13
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36";
|
|
14
|
+
const ANDROID_UA =
|
|
15
|
+
"Mozilla/5.0 (Linux; Android 16; Pixel 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Mobile Safari/537.36";
|
|
16
|
+
const WINDOWS_UA =
|
|
17
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36";
|
|
18
|
+
|
|
19
|
+
const coarse = () => ({ matches: true });
|
|
20
|
+
const fine = () => ({ matches: false });
|
|
21
|
+
|
|
22
|
+
function setNavigator(userAgent: string, maxTouchPoints: number) {
|
|
23
|
+
Object.defineProperty(window.navigator, "userAgent", { value: userAgent, configurable: true });
|
|
24
|
+
Object.defineProperty(window.navigator, "maxTouchPoints", {
|
|
25
|
+
value: maxTouchPoints,
|
|
26
|
+
configurable: true,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
setNavigator(WINDOWS_UA, 0);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("isTouchDevice", () => {
|
|
35
|
+
it("counts iPadOS Safari, which sends a Mac user agent", () => {
|
|
36
|
+
expect(isTouchDevice({ userAgent: IPADOS_SAFARI_UA, maxTouchPoints: 5 }, fine)).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("does not count a Mac", () => {
|
|
40
|
+
expect(isTouchDevice({ userAgent: IPADOS_SAFARI_UA, maxTouchPoints: 0 }, coarse)).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("counts Android's Desktop site: touch points and a coarse primary pointer", () => {
|
|
44
|
+
expect(isTouchDevice({ userAgent: ANDROID_DESKTOP_SITE_UA, maxTouchPoints: 5 }, coarse)).toBe(
|
|
45
|
+
true,
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("does not count a touch-screen laptop, whose primary pointer is fine", () => {
|
|
50
|
+
expect(isTouchDevice({ userAgent: WINDOWS_UA, maxTouchPoints: 10 }, fine)).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("is false without a navigator (SSR) or a matchMedia", () => {
|
|
54
|
+
expect(isTouchDevice(null, coarse)).toBe(false);
|
|
55
|
+
expect(isTouchDevice({ userAgent: ANDROID_DESKTOP_SITE_UA, maxTouchPoints: 5 }, null)).toBe(
|
|
56
|
+
false,
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("is false when matchMedia throws", () => {
|
|
61
|
+
const throws = () => {
|
|
62
|
+
throw new Error("no media queries");
|
|
63
|
+
};
|
|
64
|
+
expect(isTouchDevice({ userAgent: ANDROID_DESKTOP_SITE_UA, maxTouchPoints: 5 }, throws)).toBe(
|
|
65
|
+
false,
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("defaultOpenConnectorFallbackMs", () => {
|
|
71
|
+
it("is the phone default on a phone", () => {
|
|
72
|
+
setNavigator(ANDROID_UA, 5);
|
|
73
|
+
expect(defaultOpenConnectorFallbackMs()).toBe(DEFAULT_OPEN_CONNECTOR_FALLBACK_MS);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("is the phone default on an iPad that asks for the desktop site", () => {
|
|
77
|
+
setNavigator(IPADOS_SAFARI_UA, 5);
|
|
78
|
+
expect(defaultOpenConnectorFallbackMs()).toBe(DEFAULT_OPEN_CONNECTOR_FALLBACK_MS);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("is still a fallback on desktop, so an explicit call never spins forever", () => {
|
|
82
|
+
setNavigator(WINDOWS_UA, 0);
|
|
83
|
+
expect(defaultOpenConnectorFallbackMs()).toBe(DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS);
|
|
84
|
+
expect(DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS).toBeGreaterThan(0);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isMobile } from "@multiplatform.one/connectkit";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS,
|
|
5
|
+
DEFAULT_OPEN_CONNECTOR_FALLBACK_MS,
|
|
6
|
+
} from "./launcher";
|
|
7
|
+
|
|
8
|
+
type DeviceNavigator = { userAgent?: string; maxTouchPoints?: number };
|
|
9
|
+
type MatchMedia = (query: string) => { matches: boolean };
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A touch device whose browser sends a desktop user agent, which connectkit's
|
|
13
|
+
* `isMobile()` reads as desktop: iPadOS Safari sends a Mac one, and Android's
|
|
14
|
+
* "Desktop site" a Linux one. A Mac reports no touch points, and a laptop's touch
|
|
15
|
+
* screen is not its primary pointer, so neither counts.
|
|
16
|
+
*/
|
|
17
|
+
export function isTouchDevice(
|
|
18
|
+
nav: DeviceNavigator | null = typeof navigator === "undefined" ? null : navigator,
|
|
19
|
+
matchMedia: MatchMedia | null = typeof window === "undefined" || !window.matchMedia
|
|
20
|
+
? null
|
|
21
|
+
: (query) => window.matchMedia(query),
|
|
22
|
+
): boolean {
|
|
23
|
+
if (!nav || (nav.maxTouchPoints ?? 0) < 2) return false;
|
|
24
|
+
if (/Macintosh/.test(nav.userAgent ?? "")) return true;
|
|
25
|
+
try {
|
|
26
|
+
return matchMedia?.("(pointer: coarse)").matches ?? false;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The `fallbackMs` an `openConnector` call without one gets on this device. */
|
|
33
|
+
export function defaultOpenConnectorFallbackMs(): number {
|
|
34
|
+
return isMobile() || isTouchDevice()
|
|
35
|
+
? DEFAULT_OPEN_CONNECTOR_FALLBACK_MS
|
|
36
|
+
: DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS;
|
|
37
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export {
|
|
2
|
+
createConnectorLauncher,
|
|
3
|
+
DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS,
|
|
4
|
+
DEFAULT_OPEN_CONNECTOR_FALLBACK_MS,
|
|
5
|
+
type ConnectorLauncher,
|
|
6
|
+
type LauncherDeps,
|
|
7
|
+
type OpenConnectorOptions,
|
|
8
|
+
type PendingConnect,
|
|
9
|
+
} from "./launcher";
|
|
10
|
+
export {
|
|
11
|
+
ConnectorLauncherProvider,
|
|
12
|
+
getMobileOptions,
|
|
13
|
+
resolveWallet,
|
|
14
|
+
useConnectorLauncher,
|
|
15
|
+
type ConnectorLauncherValue,
|
|
16
|
+
type MobileConnectOptions,
|
|
17
|
+
type Web3ConnectKitOptions,
|
|
18
|
+
} from "./context";
|