@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,113 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { renderHook } from "@testing-library/react";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { getBase58Decoder } from "@solana/kit";
|
|
6
|
+
import { createPublicClient, createWalletClient, custom } from "viem";
|
|
7
|
+
import { mainnet } from "viem/chains";
|
|
8
|
+
import { Web3ConfigContext, type Web3Config } from "../providers/walletConfig";
|
|
9
|
+
|
|
10
|
+
const { mockUseAccount, mockUseWalletClient, mockUsePublicClient } = vi.hoisted(() => ({
|
|
11
|
+
mockUseAccount: vi.fn(),
|
|
12
|
+
mockUseWalletClient: vi.fn(),
|
|
13
|
+
mockUsePublicClient: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
vi.mock("wagmi", () => ({
|
|
17
|
+
useAccount: mockUseAccount,
|
|
18
|
+
useWalletClient: mockUseWalletClient,
|
|
19
|
+
usePublicClient: mockUsePublicClient,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
import { useBitcoinClient, useEvmClient, useSuiClient } from "./hooks";
|
|
23
|
+
import { useSolanaClient } from "./useSolanaClient";
|
|
24
|
+
|
|
25
|
+
const evmAddress = "0x1111111111111111111111111111111111111111";
|
|
26
|
+
const solanaAddress = getBase58Decoder().decode(new Uint8Array(32).fill(7));
|
|
27
|
+
const provider = { request: vi.fn() };
|
|
28
|
+
const walletClient = createWalletClient({
|
|
29
|
+
account: evmAddress,
|
|
30
|
+
chain: mainnet,
|
|
31
|
+
transport: custom(provider),
|
|
32
|
+
});
|
|
33
|
+
const publicClient = createPublicClient({ chain: mainnet, transport: custom(provider) });
|
|
34
|
+
|
|
35
|
+
const shim = (ecosystem: string, address: string) => ({
|
|
36
|
+
id: `wallet:${ecosystem}`,
|
|
37
|
+
type: "wallet",
|
|
38
|
+
ecosystem,
|
|
39
|
+
adapter: { address, signMessage: vi.fn(async () => "sig") },
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
vi.clearAllMocks();
|
|
44
|
+
mockUseWalletClient.mockReturnValue({ data: undefined });
|
|
45
|
+
mockUsePublicClient.mockReturnValue(publicClient);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe("useEvmClient", () => {
|
|
49
|
+
it("wraps the connected EVM wallet", () => {
|
|
50
|
+
mockUseAccount.mockReturnValue({ connector: { id: "metaMask" }, chainId: 1 });
|
|
51
|
+
mockUseWalletClient.mockReturnValue({ data: walletClient });
|
|
52
|
+
const { result } = renderHook(() => useEvmClient());
|
|
53
|
+
expect(result.current?.family).toBe("evm");
|
|
54
|
+
expect(result.current?.address).toBe(evmAddress);
|
|
55
|
+
expect(result.current?.chainId).toBe(1);
|
|
56
|
+
expect(mockUseWalletClient).toHaveBeenCalledWith(
|
|
57
|
+
expect.objectContaining({ query: { enabled: true } }),
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("stays undefined, and does not query, while a non-EVM wallet is connected", () => {
|
|
62
|
+
mockUseAccount.mockReturnValue({ connector: shim("solana", solanaAddress), chainId: 0x534f4c });
|
|
63
|
+
const { result } = renderHook(() => useEvmClient());
|
|
64
|
+
expect(result.current).toBeUndefined();
|
|
65
|
+
expect(mockUseWalletClient).toHaveBeenCalledWith(
|
|
66
|
+
expect.objectContaining({ query: { enabled: false } }),
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("is undefined before a wallet connects", () => {
|
|
71
|
+
mockUseAccount.mockReturnValue({ connector: undefined });
|
|
72
|
+
expect(renderHook(() => useEvmClient()).result.current).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe("useSolanaClient", () => {
|
|
77
|
+
const wrapper =
|
|
78
|
+
(config: Partial<Web3Config>) =>
|
|
79
|
+
({ children }: { children: ReactNode }) => (
|
|
80
|
+
<Web3ConfigContext.Provider value={config as Web3Config}>
|
|
81
|
+
{children}
|
|
82
|
+
</Web3ConfigContext.Provider>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
it("builds the client from the connected Solana wallet and Web3Config.solanaRpcUrl", () => {
|
|
86
|
+
mockUseAccount.mockReturnValue({
|
|
87
|
+
connector: shim("solana", solanaAddress),
|
|
88
|
+
address: solanaAddress,
|
|
89
|
+
});
|
|
90
|
+
const { result } = renderHook(() => useSolanaClient(), {
|
|
91
|
+
wrapper: wrapper({ solanaRpcUrl: "https://api.devnet.solana.com" }),
|
|
92
|
+
});
|
|
93
|
+
expect(result.current?.family).toBe("solana");
|
|
94
|
+
expect(result.current?.address).toBe(solanaAddress);
|
|
95
|
+
expect(result.current?.chainId).toBe("solana:devnet");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("is undefined for an EVM connection", () => {
|
|
99
|
+
mockUseAccount.mockReturnValue({ connector: { id: "metaMask" }, address: evmAddress });
|
|
100
|
+
expect(renderHook(() => useSolanaClient()).result.current).toBeUndefined();
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe("useSuiClient / useBitcoinClient", () => {
|
|
105
|
+
it("return the client only for their own ecosystem", () => {
|
|
106
|
+
mockUseAccount.mockReturnValue({ connector: shim("sui", "0xsui"), address: "0xsui" });
|
|
107
|
+
expect(renderHook(() => useSuiClient()).result.current?.address).toBe("0xsui");
|
|
108
|
+
expect(renderHook(() => useBitcoinClient()).result.current).toBeUndefined();
|
|
109
|
+
|
|
110
|
+
mockUseAccount.mockReturnValue({ connector: shim("bitcoin", "bc1q"), address: "bc1q" });
|
|
111
|
+
expect(renderHook(() => useBitcoinClient()).result.current?.chainId).toBe("bitcoin");
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useAccount, usePublicClient, useWalletClient } from "wagmi";
|
|
3
|
+
import { isSyntheticChainId } from "../connectkit/connectors/syntheticChains";
|
|
4
|
+
import { bitcoinClient, type BitcoinClient } from "./bitcoin";
|
|
5
|
+
import { connectorAdapter } from "./adapter";
|
|
6
|
+
import { evmClient, type EvmClient, type EvmWalletClient } from "./evm";
|
|
7
|
+
import { suiClient, type SuiClient } from "./sui";
|
|
8
|
+
import type { PublicClient } from "viem";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The connected EVM wallet as a viem WalletClient plus a PublicClient for reads,
|
|
12
|
+
* wrapped in the mpo EVM client. Undefined until an EVM wallet is connected, and
|
|
13
|
+
* while a non-EVM wallet holds the connection.
|
|
14
|
+
*/
|
|
15
|
+
export function useEvmClient(parameters: { chainId?: number } = {}): EvmClient | undefined {
|
|
16
|
+
const { connector, chainId: connectedChainId } = useAccount();
|
|
17
|
+
const evm = !!connector && !connectorAdapter(connector) && !isSyntheticChainId(connectedChainId);
|
|
18
|
+
const { data: walletClient } = useWalletClient({
|
|
19
|
+
chainId: parameters.chainId,
|
|
20
|
+
query: { enabled: evm },
|
|
21
|
+
});
|
|
22
|
+
const publicClient = usePublicClient({ chainId: walletClient?.chain.id ?? parameters.chainId });
|
|
23
|
+
return useMemo(
|
|
24
|
+
() =>
|
|
25
|
+
evm && walletClient && publicClient
|
|
26
|
+
? evmClient({
|
|
27
|
+
walletClient: walletClient as unknown as EvmWalletClient,
|
|
28
|
+
publicClient: publicClient as PublicClient,
|
|
29
|
+
})
|
|
30
|
+
: undefined,
|
|
31
|
+
[evm, walletClient, publicClient],
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The connected Sui wallet (message signing only for now). */
|
|
36
|
+
export function useSuiClient(): SuiClient | undefined {
|
|
37
|
+
const { connector, address } = useAccount();
|
|
38
|
+
return useMemo(() => {
|
|
39
|
+
const adapter = connectorAdapter(connector, "sui");
|
|
40
|
+
return adapter?.address ? suiClient(adapter) : undefined;
|
|
41
|
+
}, [connector, address]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The connected Bitcoin wallet (message signing only for now). */
|
|
45
|
+
export function useBitcoinClient(): BitcoinClient | undefined {
|
|
46
|
+
const { connector, address } = useAccount();
|
|
47
|
+
return useMemo(() => {
|
|
48
|
+
const adapter = connectorAdapter(connector, "bitcoin");
|
|
49
|
+
return adapter?.address ? bitcoinClient(adapter) : undefined;
|
|
50
|
+
}, [connector, address]);
|
|
51
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Per-chain clients: the one way an app talks to a chain through mpo web3.
|
|
2
|
+
// Each client shares { family, address, chainId?, capabilities, signMessage }
|
|
3
|
+
// and adds what its family can do. The full Solana client is the web-only
|
|
4
|
+
// `./solana` subpath, not this barrel: the root is the native entry too, and
|
|
5
|
+
// native signs Solana through the WebView bridge, so @solana/kit must never
|
|
6
|
+
// enter that bundle, and sign-in (solanaMessageClient) does not need it.
|
|
7
|
+
export {
|
|
8
|
+
UnsupportedClientMethodError,
|
|
9
|
+
type ChainClient,
|
|
10
|
+
type ClientCapability,
|
|
11
|
+
type ClientFamily,
|
|
12
|
+
} from "./types";
|
|
13
|
+
export {
|
|
14
|
+
evmClient,
|
|
15
|
+
type Erc20Actions,
|
|
16
|
+
type EvmClient,
|
|
17
|
+
type EvmClientConfig,
|
|
18
|
+
type EvmSendTransactionParameters,
|
|
19
|
+
type EvmWalletClient,
|
|
20
|
+
type EvmWriteContractParameters,
|
|
21
|
+
} from "./evm";
|
|
22
|
+
export { suiClient, type SuiClient } from "./sui";
|
|
23
|
+
export { bitcoinClient, type BitcoinClient } from "./bitcoin";
|
|
24
|
+
export {
|
|
25
|
+
assertGpgSignature,
|
|
26
|
+
createGpgSigner,
|
|
27
|
+
gpgSignCommand,
|
|
28
|
+
useGpgSigner,
|
|
29
|
+
type GpgSigner,
|
|
30
|
+
type GpgSignRequest,
|
|
31
|
+
} from "./gpg";
|
|
32
|
+
export { connectorAdapter } from "./adapter";
|
|
33
|
+
export { clientForConnector, type ConnectorClientOptions, type NonEvmClient } from "./connector";
|
|
34
|
+
export {
|
|
35
|
+
solanaMessageClient,
|
|
36
|
+
type SolanaChain,
|
|
37
|
+
type SolanaCluster,
|
|
38
|
+
type SolanaMessageClient,
|
|
39
|
+
} from "./solanaMessage";
|
|
40
|
+
export { useBitcoinClient, useEvmClient, useSuiClient } from "./hooks";
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import {
|
|
4
|
+
address,
|
|
5
|
+
appendTransactionMessageInstruction,
|
|
6
|
+
compileTransaction,
|
|
7
|
+
createTransactionMessage,
|
|
8
|
+
getBase58Decoder,
|
|
9
|
+
getBase58Encoder,
|
|
10
|
+
getCompiledTransactionMessageDecoder,
|
|
11
|
+
getTransactionDecoder,
|
|
12
|
+
getTransactionEncoder,
|
|
13
|
+
pipe,
|
|
14
|
+
setTransactionMessageFeePayer,
|
|
15
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
16
|
+
type Blockhash,
|
|
17
|
+
type Rpc,
|
|
18
|
+
type SolanaRpcApi,
|
|
19
|
+
} from "@solana/kit";
|
|
20
|
+
import {
|
|
21
|
+
connectSolanaWallet,
|
|
22
|
+
injectedSolanaSigner,
|
|
23
|
+
solanaChainFromRpcUrl,
|
|
24
|
+
solanaClient,
|
|
25
|
+
standardSolanaSigner,
|
|
26
|
+
transferSolInstruction,
|
|
27
|
+
SolanaConfirmationError,
|
|
28
|
+
type SolanaSigner,
|
|
29
|
+
} from "./solana";
|
|
30
|
+
import { UnsupportedClientMethodError } from "./types";
|
|
31
|
+
import {
|
|
32
|
+
getSolanaWallets,
|
|
33
|
+
type StandardWallet,
|
|
34
|
+
type StandardWalletAccount,
|
|
35
|
+
} from "./walletStandard";
|
|
36
|
+
|
|
37
|
+
const b58 = (bytes: Uint8Array) => getBase58Decoder().decode(bytes);
|
|
38
|
+
const owner = b58(new Uint8Array(32).fill(7));
|
|
39
|
+
const other = b58(new Uint8Array(32).fill(9));
|
|
40
|
+
// A leading zero byte is the case where base58 codecs most often disagree.
|
|
41
|
+
const signatureBytes = Uint8Array.from({ length: 64 }, (_, i) => (i === 0 ? 0 : i));
|
|
42
|
+
|
|
43
|
+
function sampleTransaction() {
|
|
44
|
+
const message = pipe(
|
|
45
|
+
createTransactionMessage({ version: 0 }),
|
|
46
|
+
(m) => setTransactionMessageFeePayer(address(owner), m),
|
|
47
|
+
(m) =>
|
|
48
|
+
setTransactionMessageLifetimeUsingBlockhash(
|
|
49
|
+
{ blockhash: b58(new Uint8Array(32).fill(3)) as Blockhash, lastValidBlockHeight: 10n },
|
|
50
|
+
m,
|
|
51
|
+
),
|
|
52
|
+
(m) =>
|
|
53
|
+
appendTransactionMessageInstruction(
|
|
54
|
+
transferSolInstruction(address(owner), address(other), 5n),
|
|
55
|
+
m,
|
|
56
|
+
),
|
|
57
|
+
);
|
|
58
|
+
return compileTransaction(message);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function mockSigner(overrides: Partial<SolanaSigner> = {}): SolanaSigner {
|
|
62
|
+
return {
|
|
63
|
+
address: owner,
|
|
64
|
+
signMessage: vi.fn(async () => signatureBytes),
|
|
65
|
+
signTransaction: vi.fn(async (tx: Uint8Array) => tx),
|
|
66
|
+
...overrides,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const registered: ((event: Event) => void)[] = [];
|
|
71
|
+
function registerWallet(wallet: StandardWallet) {
|
|
72
|
+
const listener = (event: Event) =>
|
|
73
|
+
((event as CustomEvent).detail as { register(w: StandardWallet): void }).register(wallet);
|
|
74
|
+
window.addEventListener("wallet-standard:app-ready", listener);
|
|
75
|
+
registered.push(listener);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function mockWallet(name: string, accounts: StandardWalletAccount[], withSend = true) {
|
|
79
|
+
const features: Record<string, unknown> = {
|
|
80
|
+
"standard:connect": { connect: vi.fn(async () => ({ accounts })) },
|
|
81
|
+
"solana:signMessage": {
|
|
82
|
+
signMessage: vi.fn(async () => [
|
|
83
|
+
{ signedMessage: new Uint8Array(), signature: signatureBytes },
|
|
84
|
+
]),
|
|
85
|
+
},
|
|
86
|
+
"solana:signTransaction": {
|
|
87
|
+
signTransaction: vi.fn(async ({ transaction }: { transaction: Uint8Array }) => [
|
|
88
|
+
{ signedTransaction: transaction },
|
|
89
|
+
]),
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
if (withSend) {
|
|
93
|
+
features["solana:signAndSendTransaction"] = {
|
|
94
|
+
signAndSendTransaction: vi.fn(async () => [{ signature: signatureBytes }]),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return { name, chains: ["solana:mainnet"], accounts, features } as StandardWallet;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const account = (addr: string): StandardWalletAccount => ({
|
|
101
|
+
address: addr,
|
|
102
|
+
publicKey: getBase58Encoder().encode(addr) as Uint8Array,
|
|
103
|
+
chains: ["solana:mainnet", "solana:devnet"],
|
|
104
|
+
features: [],
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
afterEach(() => {
|
|
108
|
+
for (const listener of registered.splice(0)) {
|
|
109
|
+
window.removeEventListener("wallet-standard:app-ready", listener);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe("solanaClient", () => {
|
|
114
|
+
it("shares the common client shape", () => {
|
|
115
|
+
const client = solanaClient({ signer: mockSigner(), rpcUrl: "https://api.devnet.solana.com" });
|
|
116
|
+
expect(client.family).toBe("solana");
|
|
117
|
+
expect(client.address).toBe(owner);
|
|
118
|
+
expect(client.chainId).toBe("solana:devnet");
|
|
119
|
+
expect(client.capabilities).toContain("signAndSendTransaction");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("returns the base58 signature over the UTF-8 message bytes", async () => {
|
|
123
|
+
const signer = mockSigner();
|
|
124
|
+
const client = solanaClient({ signer });
|
|
125
|
+
await expect(client.signMessage("héllo")).resolves.toBe(b58(signatureBytes));
|
|
126
|
+
expect(signer.signMessage).toHaveBeenCalledWith(new TextEncoder().encode("héllo"));
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("hands the wallet wire bytes and decodes what it signs", async () => {
|
|
130
|
+
const tx = sampleTransaction();
|
|
131
|
+
const signer = mockSigner();
|
|
132
|
+
const client = solanaClient({ signer });
|
|
133
|
+
const signed = await client.signTransaction(tx);
|
|
134
|
+
expect(signer.signTransaction).toHaveBeenCalledWith(
|
|
135
|
+
Uint8Array.from(getTransactionEncoder().encode(tx)),
|
|
136
|
+
);
|
|
137
|
+
expect(signed.messageBytes).toEqual(tx.messageBytes);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("lets the wallet sign and send when it can", async () => {
|
|
141
|
+
const signAndSendTransaction = vi.fn(async () => signatureBytes);
|
|
142
|
+
const rpc = { sendTransaction: vi.fn() } as unknown as Rpc<SolanaRpcApi>;
|
|
143
|
+
const client = solanaClient({ signer: mockSigner({ signAndSendTransaction }), rpc });
|
|
144
|
+
await expect(client.signAndSendTransaction(sampleTransaction())).resolves.toEqual({
|
|
145
|
+
signature: b58(signatureBytes),
|
|
146
|
+
lastValidBlockHeight: 10n,
|
|
147
|
+
});
|
|
148
|
+
expect(rpc.sendTransaction).not.toHaveBeenCalled();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("signs, then sends over its own RPC when the wallet cannot send", async () => {
|
|
152
|
+
const send = vi.fn(async () => "sent-signature");
|
|
153
|
+
const rpc = {
|
|
154
|
+
sendTransaction: vi.fn(() => ({ send })),
|
|
155
|
+
} as unknown as Rpc<SolanaRpcApi>;
|
|
156
|
+
const signer = mockSigner();
|
|
157
|
+
const client = solanaClient({ signer, rpc });
|
|
158
|
+
await expect(client.signAndSendTransaction(sampleTransaction())).resolves.toEqual({
|
|
159
|
+
signature: "sent-signature",
|
|
160
|
+
lastValidBlockHeight: 10n,
|
|
161
|
+
});
|
|
162
|
+
expect(signer.signTransaction).toHaveBeenCalledOnce();
|
|
163
|
+
expect(rpc.sendTransaction).toHaveBeenCalledWith(expect.any(String), { encoding: "base64" });
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("falls back to sign-then-send when sign-and-send is unsupported", async () => {
|
|
167
|
+
const send = vi.fn(async () => "sent-signature");
|
|
168
|
+
const rpc = { sendTransaction: vi.fn(() => ({ send })) } as unknown as Rpc<SolanaRpcApi>;
|
|
169
|
+
const signAndSendTransaction = vi.fn(async () => {
|
|
170
|
+
throw new UnsupportedClientMethodError("solana", "signAndSendTransaction");
|
|
171
|
+
});
|
|
172
|
+
const client = solanaClient({ signer: mockSigner({ signAndSendTransaction }), rpc });
|
|
173
|
+
await expect(client.signAndSendTransaction(sampleTransaction())).resolves.toMatchObject({
|
|
174
|
+
signature: "sent-signature",
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("has no lastValidBlockHeight for wire bytes, which carry no lifetime", async () => {
|
|
179
|
+
const send = vi.fn(async () => "sent-signature");
|
|
180
|
+
const rpc = { sendTransaction: vi.fn(() => ({ send })) } as unknown as Rpc<SolanaRpcApi>;
|
|
181
|
+
const wire = Uint8Array.from(getTransactionEncoder().encode(sampleTransaction()));
|
|
182
|
+
await expect(
|
|
183
|
+
solanaClient({ signer: mockSigner(), rpc }).sendTransaction(wire),
|
|
184
|
+
).resolves.toEqual({
|
|
185
|
+
signature: "sent-signature",
|
|
186
|
+
lastValidBlockHeight: undefined,
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("confirms by polling signature status and surfaces a failed transaction", async () => {
|
|
191
|
+
const statuses = [
|
|
192
|
+
null,
|
|
193
|
+
{ confirmationStatus: "processed" },
|
|
194
|
+
{ confirmationStatus: "confirmed" },
|
|
195
|
+
];
|
|
196
|
+
const rpc = {
|
|
197
|
+
getSignatureStatuses: vi.fn(() => ({ send: async () => ({ value: [statuses.shift()] }) })),
|
|
198
|
+
} as unknown as Rpc<SolanaRpcApi>;
|
|
199
|
+
const client = solanaClient({ signer: mockSigner(), rpc });
|
|
200
|
+
await expect(client.confirmTransaction("sig" as never, { pollMs: 0 })).resolves.toBeUndefined();
|
|
201
|
+
|
|
202
|
+
const failing = {
|
|
203
|
+
getSignatureStatuses: () => ({
|
|
204
|
+
send: async () => ({ value: [{ err: { InstructionError: [0, "x"] } }] }),
|
|
205
|
+
}),
|
|
206
|
+
} as unknown as Rpc<SolanaRpcApi>;
|
|
207
|
+
const error = await solanaClient({ signer: mockSigner(), rpc: failing })
|
|
208
|
+
.confirmTransaction("sig" as never)
|
|
209
|
+
.catch((e: unknown) => e);
|
|
210
|
+
expect(error).toBeInstanceOf(SolanaConfirmationError);
|
|
211
|
+
expect(error).toMatchObject({ reason: "failed", mayStillLand: false });
|
|
212
|
+
expect((error as Error).message).toMatch(/failed on chain.*safe to retry/);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe("confirmTransaction against the blockhash lifetime", () => {
|
|
217
|
+
// A chain whose block height walks through `heights` (the last one repeats)
|
|
218
|
+
// while the signature has the statuses in `statuses` (null once they run out).
|
|
219
|
+
function chain(heights: bigint[], statuses: ({ confirmationStatus: string } | null)[]) {
|
|
220
|
+
const height = [...heights];
|
|
221
|
+
const status = [...statuses];
|
|
222
|
+
return {
|
|
223
|
+
getSignatureStatuses: vi.fn(() => ({
|
|
224
|
+
send: async () => ({ value: [status.length ? status.shift() : null] }),
|
|
225
|
+
})),
|
|
226
|
+
getBlockHeight: vi.fn(() => ({
|
|
227
|
+
send: async () => (height.length > 1 ? height.shift() : height[0]),
|
|
228
|
+
})),
|
|
229
|
+
} as unknown as Rpc<SolanaRpcApi> & {
|
|
230
|
+
getBlockHeight: ReturnType<typeof vi.fn>;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
it("keeps waiting past any fixed timeout while the blockhash is still valid", async () => {
|
|
235
|
+
const rpc = chain([5n, 8n, 10n], [null, null, null, { confirmationStatus: "confirmed" }]);
|
|
236
|
+
const client = solanaClient({ signer: mockSigner(), rpc });
|
|
237
|
+
await expect(
|
|
238
|
+
client.confirmTransaction(
|
|
239
|
+
{ signature: "sig" as never, lastValidBlockHeight: 10n },
|
|
240
|
+
{ timeoutMs: 0, pollMs: 0 },
|
|
241
|
+
),
|
|
242
|
+
).resolves.toBeUndefined();
|
|
243
|
+
expect(rpc.getBlockHeight).toHaveBeenCalledTimes(3);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("fails as expired, safe to retry, once the height passes lastValidBlockHeight", async () => {
|
|
247
|
+
const rpc = chain([9n, 11n], []);
|
|
248
|
+
const error = await solanaClient({ signer: mockSigner(), rpc })
|
|
249
|
+
.confirmTransaction({ signature: "sig" as never, lastValidBlockHeight: 10n }, { pollMs: 0 })
|
|
250
|
+
.catch((e: unknown) => e);
|
|
251
|
+
expect(error).toBeInstanceOf(SolanaConfirmationError);
|
|
252
|
+
expect(error).toMatchObject({ reason: "expired", mayStillLand: false });
|
|
253
|
+
expect((error as Error).message).toMatch(/block height 11 passed 10.*will not land/);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it("confirms a transaction that landed in the last valid block", async () => {
|
|
257
|
+
const rpc = chain([11n], [null, { confirmationStatus: "confirmed" }]);
|
|
258
|
+
await expect(
|
|
259
|
+
solanaClient({ signer: mockSigner(), rpc }).confirmTransaction(
|
|
260
|
+
{ signature: "sig" as never, lastValidBlockHeight: 10n },
|
|
261
|
+
{ pollMs: 0 },
|
|
262
|
+
),
|
|
263
|
+
).resolves.toBeUndefined();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("without a lastValidBlockHeight, times out saying it may still land", async () => {
|
|
267
|
+
const rpc = chain([1n], []);
|
|
268
|
+
const error = await solanaClient({ signer: mockSigner(), rpc })
|
|
269
|
+
.confirmTransaction("sig" as never, { timeoutMs: 1, pollMs: 1 })
|
|
270
|
+
.catch((e: unknown) => e);
|
|
271
|
+
expect(error).toMatchObject({ reason: "timeout", mayStillLand: true });
|
|
272
|
+
expect((error as Error).message).toMatch(/may still land, so do not resend/);
|
|
273
|
+
expect(rpc.getBlockHeight).not.toHaveBeenCalled();
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe("transferSol", () => {
|
|
278
|
+
const blockhash = b58(new Uint8Array(32).fill(4));
|
|
279
|
+
|
|
280
|
+
function rpcFor(send: () => Promise<string>) {
|
|
281
|
+
return {
|
|
282
|
+
getLatestBlockhash: vi.fn(() => ({
|
|
283
|
+
send: async () => ({ value: { blockhash, lastValidBlockHeight: 99n } }),
|
|
284
|
+
})),
|
|
285
|
+
sendTransaction: vi.fn(() => ({ send })),
|
|
286
|
+
} as unknown as Rpc<SolanaRpcApi> & { sendTransaction: ReturnType<typeof vi.fn> };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
it("builds a System Program transfer on the latest blockhash, signs, sends it, and returns its lifetime", async () => {
|
|
290
|
+
const rpc = rpcFor(async () => "sent-signature");
|
|
291
|
+
const signer = mockSigner();
|
|
292
|
+
const client = solanaClient({ signer, rpc });
|
|
293
|
+
await expect(client.transferSol({ to: other, lamports: 1_500_000n })).resolves.toEqual({
|
|
294
|
+
signature: "sent-signature",
|
|
295
|
+
lastValidBlockHeight: 99n,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const wire = vi.mocked(signer.signTransaction).mock.calls[0][0];
|
|
299
|
+
const tx = getTransactionDecoder().decode(wire);
|
|
300
|
+
const message = getCompiledTransactionMessageDecoder().decode(tx.messageBytes);
|
|
301
|
+
expect(message.lifetimeToken).toBe(blockhash);
|
|
302
|
+
expect(message.staticAccounts[0]).toBe(owner);
|
|
303
|
+
if (!("instructions" in message)) throw new Error("expected a v0 message");
|
|
304
|
+
expect(message.instructions).toHaveLength(1);
|
|
305
|
+
const [ix] = message.instructions;
|
|
306
|
+
expect(message.staticAccounts[ix.programAddressIndex]).toBe("11111111111111111111111111111111");
|
|
307
|
+
expect(Array.from(ix.data ?? [])).toEqual(
|
|
308
|
+
Array.from(transferSolInstruction(address(owner), address(other), 1_500_000n).data ?? []),
|
|
309
|
+
);
|
|
310
|
+
expect(ix.accountIndices?.map((i) => message.staticAccounts[i])).toEqual([owner, other]);
|
|
311
|
+
expect(rpc.sendTransaction).toHaveBeenCalledWith(expect.any(String), { encoding: "base64" });
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("returns the lifetime when the wallet signs and sends it too", async () => {
|
|
315
|
+
const rpc = rpcFor(async () => "unused");
|
|
316
|
+
const signAndSendTransaction = vi.fn(async () => signatureBytes);
|
|
317
|
+
const client = solanaClient({ signer: mockSigner({ signAndSendTransaction }), rpc });
|
|
318
|
+
await expect(client.transferSol({ to: other, lamports: 1n })).resolves.toEqual({
|
|
319
|
+
signature: b58(signatureBytes),
|
|
320
|
+
lastValidBlockHeight: 99n,
|
|
321
|
+
});
|
|
322
|
+
expect(rpc.sendTransaction).not.toHaveBeenCalled();
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it("refuses lamports outside a u64 before asking the wallet", async () => {
|
|
326
|
+
const rpc = rpcFor(async () => "unused");
|
|
327
|
+
const signer = mockSigner();
|
|
328
|
+
const client = solanaClient({ signer, rpc });
|
|
329
|
+
await expect(client.transferSol({ to: other, lamports: -1n })).rejects.toBeInstanceOf(
|
|
330
|
+
RangeError,
|
|
331
|
+
);
|
|
332
|
+
await expect(client.transferSol({ to: other, lamports: 2n ** 64n })).rejects.toThrow(/u64/);
|
|
333
|
+
expect(signer.signTransaction).not.toHaveBeenCalled();
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
describe("transferSolInstruction", () => {
|
|
338
|
+
it("encodes System Program Transfer with little-endian lamports", () => {
|
|
339
|
+
const ix = transferSolInstruction(address(owner), address(other), 0x0102030405n);
|
|
340
|
+
expect(ix.programAddress).toBe("11111111111111111111111111111111");
|
|
341
|
+
expect(Array.from(ix.data ?? [])).toEqual([2, 0, 0, 0, 5, 4, 3, 2, 1, 0, 0, 0]);
|
|
342
|
+
expect(ix.accounts?.map((a) => [a.address, a.role])).toEqual([
|
|
343
|
+
[owner, 3],
|
|
344
|
+
[other, 1],
|
|
345
|
+
]);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it("takes the full u64 range and nothing outside it", () => {
|
|
349
|
+
const max = 2n ** 64n - 1n;
|
|
350
|
+
expect(
|
|
351
|
+
Array.from(transferSolInstruction(address(owner), address(other), max).data ?? []),
|
|
352
|
+
).toEqual([2, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255]);
|
|
353
|
+
expect(() => transferSolInstruction(address(owner), address(other), 2n ** 64n)).toThrow(
|
|
354
|
+
RangeError,
|
|
355
|
+
);
|
|
356
|
+
expect(() => transferSolInstruction(address(owner), address(other), -1n)).toThrow(RangeError);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
describe("solanaChainFromRpcUrl", () => {
|
|
361
|
+
it("maps endpoints to Wallet Standard chains", () => {
|
|
362
|
+
expect(solanaChainFromRpcUrl()).toBe("solana:mainnet");
|
|
363
|
+
expect(solanaChainFromRpcUrl("https://api.devnet.solana.com")).toBe("solana:devnet");
|
|
364
|
+
expect(solanaChainFromRpcUrl("https://api.testnet.solana.com")).toBe("solana:testnet");
|
|
365
|
+
expect(solanaChainFromRpcUrl("http://127.0.0.1:8899")).toBe("solana:localnet");
|
|
366
|
+
expect(solanaChainFromRpcUrl("https://rpc.helius.xyz/?api-key=x")).toBe("solana:mainnet");
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
describe("Wallet Standard signers", () => {
|
|
371
|
+
it("finds registered Solana wallets", () => {
|
|
372
|
+
registerWallet(mockWallet("Phantom", [account(owner)]));
|
|
373
|
+
registerWallet({ name: "Sui only", chains: [], accounts: [], features: {} } as StandardWallet);
|
|
374
|
+
expect(getSolanaWallets().map((w) => w.name)).toEqual(["Phantom"]);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it("passes the account and chain to the wallet's features", async () => {
|
|
378
|
+
const wallet = mockWallet("Phantom", [account(owner)]);
|
|
379
|
+
const signer = standardSolanaSigner(wallet, wallet.accounts[0], "solana:devnet");
|
|
380
|
+
const wire = new Uint8Array([1, 2, 3]);
|
|
381
|
+
await signer.signTransaction(wire);
|
|
382
|
+
await signer.signAndSendTransaction?.(wire);
|
|
383
|
+
const features = wallet.features as Record<string, Record<string, ReturnType<typeof vi.fn>>>;
|
|
384
|
+
expect(features["solana:signTransaction"].signTransaction).toHaveBeenCalledWith({
|
|
385
|
+
account: wallet.accounts[0],
|
|
386
|
+
transaction: wire,
|
|
387
|
+
chain: "solana:devnet",
|
|
388
|
+
});
|
|
389
|
+
expect(features["solana:signAndSendTransaction"].signAndSendTransaction).toHaveBeenCalledWith({
|
|
390
|
+
account: wallet.accounts[0],
|
|
391
|
+
transaction: wire,
|
|
392
|
+
chain: "solana:devnet",
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it("leaves sign-and-send off a wallet that lacks it", () => {
|
|
397
|
+
const wallet = mockWallet("Plain", [account(owner)], false);
|
|
398
|
+
expect(standardSolanaSigner(wallet, wallet.accounts[0]).signAndSendTransaction).toBeUndefined();
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("connects a wallet by name without the modal", async () => {
|
|
402
|
+
registerWallet(mockWallet("Phantom", [account(other)]));
|
|
403
|
+
registerWallet(mockWallet("Solflare", [account(owner)]));
|
|
404
|
+
const signer = await connectSolanaWallet({ wallet: "solflare" });
|
|
405
|
+
expect(signer.address).toBe(owner);
|
|
406
|
+
await expect(connectSolanaWallet({ wallet: "Backpack" })).rejects.toThrow(/Backpack/);
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
describe("injectedSolanaSigner", () => {
|
|
411
|
+
const adapter = () => ({ address: owner, signMessage: vi.fn(async () => b58(signatureBytes)) });
|
|
412
|
+
|
|
413
|
+
it("signs text through the adapter exactly as login did, byte-for-byte", async () => {
|
|
414
|
+
const a = adapter();
|
|
415
|
+
const client = solanaClient({ signer: injectedSolanaSigner(a) });
|
|
416
|
+
const message = "example.com wants you to sign in with your Solana account:\n" + owner;
|
|
417
|
+
await expect(client.signMessage(message)).resolves.toBe(b58(signatureBytes));
|
|
418
|
+
expect(a.signMessage).toHaveBeenCalledWith(message);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it("sends non-text bytes and transactions to the Wallet Standard wallet holding the address", async () => {
|
|
422
|
+
const wallet = mockWallet("Phantom", [account(owner)]);
|
|
423
|
+
registerWallet(mockWallet("Other", [account(other)]));
|
|
424
|
+
registerWallet(wallet);
|
|
425
|
+
const a = adapter();
|
|
426
|
+
const signer = injectedSolanaSigner(a);
|
|
427
|
+
await signer.signMessage(new Uint8Array([0xff, 0xfe]));
|
|
428
|
+
await signer.signTransaction(new Uint8Array([1]));
|
|
429
|
+
await signer.signAndSendTransaction?.(new Uint8Array([1]));
|
|
430
|
+
expect(a.signMessage).not.toHaveBeenCalled();
|
|
431
|
+
const features = wallet.features as Record<string, Record<string, ReturnType<typeof vi.fn>>>;
|
|
432
|
+
expect(features["solana:signMessage"].signMessage).toHaveBeenCalledOnce();
|
|
433
|
+
expect(features["solana:signTransaction"].signTransaction).toHaveBeenCalledOnce();
|
|
434
|
+
expect(features["solana:signAndSendTransaction"].signAndSendTransaction).toHaveBeenCalledOnce();
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it("says which address has no transaction-capable wallet", async () => {
|
|
438
|
+
const signer = injectedSolanaSigner(adapter());
|
|
439
|
+
await expect(signer.signTransaction(new Uint8Array([1]))).rejects.toBeInstanceOf(
|
|
440
|
+
UnsupportedClientMethodError,
|
|
441
|
+
);
|
|
442
|
+
await expect(signer.signTransaction(new Uint8Array([1]))).rejects.toThrow(owner);
|
|
443
|
+
});
|
|
444
|
+
});
|