@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,465 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AccountRole,
|
|
3
|
+
address,
|
|
4
|
+
appendTransactionMessageInstruction,
|
|
5
|
+
compileTransaction,
|
|
6
|
+
createSolanaRpc,
|
|
7
|
+
createTransactionMessage,
|
|
8
|
+
getBase58Decoder,
|
|
9
|
+
getBase58Encoder,
|
|
10
|
+
getBase64EncodedWireTransaction,
|
|
11
|
+
getTransactionDecoder,
|
|
12
|
+
getTransactionEncoder,
|
|
13
|
+
pipe,
|
|
14
|
+
setTransactionMessageFeePayer,
|
|
15
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
16
|
+
type Address,
|
|
17
|
+
type Instruction,
|
|
18
|
+
type Rpc,
|
|
19
|
+
type Signature,
|
|
20
|
+
type SolanaRpcApi,
|
|
21
|
+
type Transaction,
|
|
22
|
+
} from "@solana/kit";
|
|
23
|
+
import type { WalletAdapter } from "../connectkit/adapters/types";
|
|
24
|
+
import type { SolanaChain } from "./solanaMessage";
|
|
25
|
+
import { UnsupportedClientMethodError, type ChainClient, type ClientCapability } from "./types";
|
|
26
|
+
import {
|
|
27
|
+
getSolanaWallets,
|
|
28
|
+
SolanaSignAndSendTransaction,
|
|
29
|
+
SolanaSignMessage,
|
|
30
|
+
SolanaSignTransaction,
|
|
31
|
+
StandardConnect,
|
|
32
|
+
type SolanaSignAndSendTransactionFeature,
|
|
33
|
+
type SolanaSignMessageFeature,
|
|
34
|
+
type SolanaSignTransactionFeature,
|
|
35
|
+
type StandardConnectFeature,
|
|
36
|
+
type StandardWallet,
|
|
37
|
+
type StandardWalletAccount,
|
|
38
|
+
} from "./walletStandard";
|
|
39
|
+
|
|
40
|
+
export type { SolanaChain, SolanaCluster } from "./solanaMessage";
|
|
41
|
+
|
|
42
|
+
export const solanaRpcUrls: Record<SolanaChain, string> = {
|
|
43
|
+
"solana:mainnet": "https://api.mainnet-beta.solana.com",
|
|
44
|
+
"solana:devnet": "https://api.devnet.solana.com",
|
|
45
|
+
"solana:testnet": "https://api.testnet.solana.com",
|
|
46
|
+
"solana:localnet": "http://127.0.0.1:8899",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** Guess the cluster from an RPC URL, so a devnet `solanaRpcUrl` does not ask the wallet to sign for mainnet. */
|
|
50
|
+
export function solanaChainFromRpcUrl(rpcUrl?: string): SolanaChain {
|
|
51
|
+
if (!rpcUrl) return "solana:mainnet";
|
|
52
|
+
if (/devnet/i.test(rpcUrl)) return "solana:devnet";
|
|
53
|
+
if (/testnet/i.test(rpcUrl)) return "solana:testnet";
|
|
54
|
+
if (/\/\/(localhost|127\.0\.0\.1|10\.0\.2\.2|\[::1\])[:/]/i.test(rpcUrl))
|
|
55
|
+
return "solana:localnet";
|
|
56
|
+
return "solana:mainnet";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The byte-level wallet a Solana client drives. Messages and transactions cross
|
|
61
|
+
* as raw bytes (wire-format transactions), so the same client runs over the
|
|
62
|
+
* Wallet Standard on web today and a deeplink wallet later.
|
|
63
|
+
*/
|
|
64
|
+
export interface SolanaSigner {
|
|
65
|
+
readonly address: string;
|
|
66
|
+
/** Returns the 64-byte ed25519 signature. */
|
|
67
|
+
signMessage(message: Uint8Array): Promise<Uint8Array>;
|
|
68
|
+
/** Returns the signed wire transaction. */
|
|
69
|
+
signTransaction(transaction: Uint8Array): Promise<Uint8Array>;
|
|
70
|
+
/** Returns the 64-byte transaction signature. Optional: without it the client signs, then sends over its own RPC. */
|
|
71
|
+
signAndSendTransaction?(transaction: Uint8Array): Promise<Uint8Array>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface SolanaClientConfig {
|
|
75
|
+
signer: SolanaSigner;
|
|
76
|
+
/** JSON-RPC endpoint, usually `Web3Config.solanaRpcUrl`. Defaults to the chain's public endpoint. */
|
|
77
|
+
rpcUrl?: string;
|
|
78
|
+
/** A ready kit RPC client; wins over `rpcUrl`. */
|
|
79
|
+
rpc?: Rpc<SolanaRpcApi>;
|
|
80
|
+
/** Defaults to the cluster `rpcUrl` points at. */
|
|
81
|
+
chain?: SolanaChain;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* A sent transaction. `lastValidBlockHeight` is known when the client saw the
|
|
86
|
+
* blockhash (transferSol, or a kit transaction carrying its lifetime), and is
|
|
87
|
+
* what lets confirmTransaction tell "expired, safe to retry" from "still pending".
|
|
88
|
+
*/
|
|
89
|
+
export interface SolanaSubmission {
|
|
90
|
+
signature: Signature;
|
|
91
|
+
lastValidBlockHeight?: bigint;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type SolanaConfirmationFailure = "failed" | "expired" | "timeout";
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* confirmTransaction's failure. `mayStillLand` is the part a caller acts on:
|
|
98
|
+
* resending while it is true can pay twice.
|
|
99
|
+
*/
|
|
100
|
+
export class SolanaConfirmationError extends Error {
|
|
101
|
+
readonly mayStillLand: boolean;
|
|
102
|
+
constructor(
|
|
103
|
+
readonly signature: Signature,
|
|
104
|
+
readonly reason: SolanaConfirmationFailure,
|
|
105
|
+
detail: string,
|
|
106
|
+
) {
|
|
107
|
+
const mayStillLand = reason === "timeout";
|
|
108
|
+
super(
|
|
109
|
+
`solana transaction ${signature} ${detail}; ${
|
|
110
|
+
mayStillLand
|
|
111
|
+
? "it may still land, so do not resend it until its blockhash expires"
|
|
112
|
+
: "it will not land, so it is safe to retry"
|
|
113
|
+
}`,
|
|
114
|
+
);
|
|
115
|
+
this.name = "SolanaConfirmationError";
|
|
116
|
+
this.mayStillLand = mayStillLand;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface SolanaConfirmOptions {
|
|
121
|
+
commitment?: "confirmed" | "finalized";
|
|
122
|
+
/** Overrides the submission's. With it, failure waits for the blockhash to expire, however long that takes. */
|
|
123
|
+
lastValidBlockHeight?: bigint;
|
|
124
|
+
/** Only used without a lastValidBlockHeight; that failure says the transaction may still land. */
|
|
125
|
+
timeoutMs?: number;
|
|
126
|
+
pollMs?: number;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface SolanaClient extends ChainClient<"solana"> {
|
|
130
|
+
readonly address: Address;
|
|
131
|
+
readonly chainId: SolanaChain;
|
|
132
|
+
readonly rpc: Rpc<SolanaRpcApi>;
|
|
133
|
+
readonly signer: SolanaSigner;
|
|
134
|
+
/** Signs the UTF-8 bytes of a string (or raw bytes); returns the base58 signature. */
|
|
135
|
+
signMessage(message: string | Uint8Array): Promise<string>;
|
|
136
|
+
signTransaction(transaction: Transaction | Uint8Array): Promise<Transaction>;
|
|
137
|
+
/** The wallet signs and broadcasts when it can (Phantom asks for this); otherwise sign, then send over `rpc`. */
|
|
138
|
+
signAndSendTransaction(transaction: Transaction | Uint8Array): Promise<SolanaSubmission>;
|
|
139
|
+
/** Broadcasts an already signed transaction over `rpc`. */
|
|
140
|
+
sendTransaction(transaction: Transaction | Uint8Array): Promise<SolanaSubmission>;
|
|
141
|
+
/**
|
|
142
|
+
* Resolves once the transaction reaches `commitment`. Rejects with
|
|
143
|
+
* SolanaConfirmationError: `failed` (it landed and errored), `expired` (block
|
|
144
|
+
* height passed lastValidBlockHeight without it, safe to retry) or `timeout`
|
|
145
|
+
* (no lastValidBlockHeight to judge by, so it may still land).
|
|
146
|
+
*/
|
|
147
|
+
confirmTransaction(
|
|
148
|
+
submission: SolanaSubmission | Signature,
|
|
149
|
+
options?: SolanaConfirmOptions,
|
|
150
|
+
): Promise<void>;
|
|
151
|
+
/** Lamports held by `owner`, the connected address by default. */
|
|
152
|
+
getBalance(owner?: string): Promise<bigint>;
|
|
153
|
+
/** Builds a System Program transfer, signs and sends it, and returns its lastValidBlockHeight. */
|
|
154
|
+
transferSol(args: { to: string; lamports: bigint }): Promise<SolanaSubmission>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const capabilities: readonly ClientCapability[] = [
|
|
158
|
+
"signMessage",
|
|
159
|
+
"signTransaction",
|
|
160
|
+
"signAndSendTransaction",
|
|
161
|
+
"sendTransaction",
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
const systemProgram = address("11111111111111111111111111111111");
|
|
165
|
+
const maxU64 = 0xffffffffffffffffn;
|
|
166
|
+
|
|
167
|
+
/** System Program `Transfer` (instruction index 2, then the lamports as a little-endian u64). */
|
|
168
|
+
export function transferSolInstruction(from: Address, to: Address, lamports: bigint): Instruction {
|
|
169
|
+
if (lamports < 0n || lamports > maxU64) {
|
|
170
|
+
throw new RangeError(`lamports must fit a u64, got ${lamports}`);
|
|
171
|
+
}
|
|
172
|
+
const data = new Uint8Array(12);
|
|
173
|
+
data[0] = 2;
|
|
174
|
+
let value = lamports;
|
|
175
|
+
for (let i = 4; i < 12; i++) {
|
|
176
|
+
data[i] = Number(value & 0xffn);
|
|
177
|
+
value >>= 8n;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
programAddress: systemProgram,
|
|
181
|
+
accounts: [
|
|
182
|
+
{ address: from, role: AccountRole.WRITABLE_SIGNER },
|
|
183
|
+
{ address: to, role: AccountRole.WRITABLE },
|
|
184
|
+
],
|
|
185
|
+
data,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const toWire = (transaction: Transaction | Uint8Array): Uint8Array =>
|
|
190
|
+
transaction instanceof Uint8Array
|
|
191
|
+
? transaction
|
|
192
|
+
: Uint8Array.from(getTransactionEncoder().encode(transaction));
|
|
193
|
+
|
|
194
|
+
const fromWire = (bytes: Uint8Array): Transaction => getTransactionDecoder().decode(bytes);
|
|
195
|
+
|
|
196
|
+
const toSignature = (bytes: Uint8Array): Signature => getBase58Decoder().decode(bytes) as Signature;
|
|
197
|
+
|
|
198
|
+
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
199
|
+
|
|
200
|
+
const lastValidBlockHeightOf = (transaction: Transaction | Uint8Array): bigint | undefined => {
|
|
201
|
+
if (transaction instanceof Uint8Array) return undefined;
|
|
202
|
+
const lifetime = (transaction as { lifetimeConstraint?: { lastValidBlockHeight?: bigint } })
|
|
203
|
+
.lifetimeConstraint;
|
|
204
|
+
return lifetime?.lastValidBlockHeight;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
type SignatureStatus = {
|
|
208
|
+
err: unknown;
|
|
209
|
+
confirmationStatus: "processed" | "confirmed" | "finalized" | null;
|
|
210
|
+
} | null;
|
|
211
|
+
|
|
212
|
+
const reached = (status: SignatureStatus, commitment: "confirmed" | "finalized") =>
|
|
213
|
+
status?.confirmationStatus === "finalized" ||
|
|
214
|
+
(commitment === "confirmed" && status?.confirmationStatus === "confirmed");
|
|
215
|
+
|
|
216
|
+
export function solanaClient(config: SolanaClientConfig): SolanaClient {
|
|
217
|
+
const { signer } = config;
|
|
218
|
+
const chain = config.chain ?? solanaChainFromRpcUrl(config.rpcUrl);
|
|
219
|
+
const rpc: Rpc<SolanaRpcApi> =
|
|
220
|
+
config.rpc ?? (createSolanaRpc(config.rpcUrl ?? solanaRpcUrls[chain]) as Rpc<SolanaRpcApi>);
|
|
221
|
+
const owner = address(signer.address);
|
|
222
|
+
|
|
223
|
+
const signTransaction = async (transaction: Transaction | Uint8Array) =>
|
|
224
|
+
fromWire(await signer.signTransaction(toWire(transaction)));
|
|
225
|
+
|
|
226
|
+
const broadcast = (transaction: Transaction | Uint8Array): Promise<Signature> => {
|
|
227
|
+
const tx = transaction instanceof Uint8Array ? fromWire(transaction) : transaction;
|
|
228
|
+
return rpc.sendTransaction(getBase64EncodedWireTransaction(tx), { encoding: "base64" }).send();
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const sendTransaction = async (
|
|
232
|
+
transaction: Transaction | Uint8Array,
|
|
233
|
+
): Promise<SolanaSubmission> => ({
|
|
234
|
+
signature: await broadcast(transaction),
|
|
235
|
+
lastValidBlockHeight: lastValidBlockHeightOf(transaction),
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const signAndSendTransaction = async (
|
|
239
|
+
transaction: Transaction | Uint8Array,
|
|
240
|
+
): Promise<SolanaSubmission> => {
|
|
241
|
+
const lastValidBlockHeight = lastValidBlockHeightOf(transaction);
|
|
242
|
+
const wire = toWire(transaction);
|
|
243
|
+
if (signer.signAndSendTransaction) {
|
|
244
|
+
try {
|
|
245
|
+
const signature = toSignature(await signer.signAndSendTransaction(wire));
|
|
246
|
+
return { signature, lastValidBlockHeight };
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (!(error instanceof UnsupportedClientMethodError)) throw error;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { signature: await broadcast(await signer.signTransaction(wire)), lastValidBlockHeight };
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const statusOf = async (signature: Signature): Promise<SignatureStatus> => {
|
|
255
|
+
const { value } = await rpc
|
|
256
|
+
.getSignatureStatuses([signature], { searchTransactionHistory: true })
|
|
257
|
+
.send();
|
|
258
|
+
const status = value[0] as SignatureStatus;
|
|
259
|
+
if (status?.err) {
|
|
260
|
+
throw new SolanaConfirmationError(
|
|
261
|
+
signature,
|
|
262
|
+
"failed",
|
|
263
|
+
`failed on chain: ${JSON.stringify(status.err, (_, v) => (typeof v === "bigint" ? `${v}` : v))}`,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
return status;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
family: "solana",
|
|
271
|
+
address: owner,
|
|
272
|
+
chainId: chain,
|
|
273
|
+
capabilities,
|
|
274
|
+
rpc,
|
|
275
|
+
signer,
|
|
276
|
+
async signMessage(message) {
|
|
277
|
+
const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
278
|
+
return getBase58Decoder().decode(await signer.signMessage(bytes));
|
|
279
|
+
},
|
|
280
|
+
signTransaction,
|
|
281
|
+
signAndSendTransaction,
|
|
282
|
+
sendTransaction,
|
|
283
|
+
async confirmTransaction(submission, options = {}) {
|
|
284
|
+
const { signature, lastValidBlockHeight: submitted } =
|
|
285
|
+
typeof submission === "string" ? { signature: submission } : submission;
|
|
286
|
+
const {
|
|
287
|
+
commitment = "confirmed",
|
|
288
|
+
lastValidBlockHeight = submitted,
|
|
289
|
+
timeoutMs = 90_000,
|
|
290
|
+
pollMs = 500,
|
|
291
|
+
} = options;
|
|
292
|
+
const deadline = Date.now() + timeoutMs;
|
|
293
|
+
for (;;) {
|
|
294
|
+
if (reached(await statusOf(signature), commitment)) return;
|
|
295
|
+
if (lastValidBlockHeight !== undefined) {
|
|
296
|
+
const height = await rpc.getBlockHeight({ commitment }).send();
|
|
297
|
+
if (height > lastValidBlockHeight) {
|
|
298
|
+
// It can no longer be included, but it may have been in the last valid block.
|
|
299
|
+
const status = await statusOf(signature);
|
|
300
|
+
if (reached(status, commitment)) return;
|
|
301
|
+
if (!status) {
|
|
302
|
+
throw new SolanaConfirmationError(
|
|
303
|
+
signature,
|
|
304
|
+
"expired",
|
|
305
|
+
`expired: block height ${height} passed ${lastValidBlockHeight}`,
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} else if (Date.now() > deadline) {
|
|
310
|
+
throw new SolanaConfirmationError(
|
|
311
|
+
signature,
|
|
312
|
+
"timeout",
|
|
313
|
+
`not ${commitment} after ${timeoutMs}ms`,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
await sleep(pollMs);
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
async getBalance(target) {
|
|
320
|
+
const { value } = await rpc.getBalance(target ? address(target) : owner).send();
|
|
321
|
+
return value;
|
|
322
|
+
},
|
|
323
|
+
async transferSol({ to, lamports }) {
|
|
324
|
+
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
325
|
+
const message = pipe(
|
|
326
|
+
createTransactionMessage({ version: 0 }),
|
|
327
|
+
(m) => setTransactionMessageFeePayer(owner, m),
|
|
328
|
+
(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
|
|
329
|
+
(m) =>
|
|
330
|
+
appendTransactionMessageInstruction(
|
|
331
|
+
transferSolInstruction(owner, address(to), lamports),
|
|
332
|
+
m,
|
|
333
|
+
),
|
|
334
|
+
);
|
|
335
|
+
const { signature } = await signAndSendTransaction(compileTransaction(message));
|
|
336
|
+
return { signature, lastValidBlockHeight: latestBlockhash.lastValidBlockHeight };
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function walletFeature<T>(wallet: StandardWallet, name: string): T {
|
|
342
|
+
const feature = wallet.features[name] as T | undefined;
|
|
343
|
+
if (!feature) {
|
|
344
|
+
throw new UnsupportedClientMethodError("solana", name, `${wallet.name} does not implement it`);
|
|
345
|
+
}
|
|
346
|
+
return feature;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** A SolanaSigner over one Wallet Standard wallet account (Phantom, Solflare, Backpack on web). */
|
|
350
|
+
export function standardSolanaSigner(
|
|
351
|
+
wallet: StandardWallet,
|
|
352
|
+
account: StandardWalletAccount,
|
|
353
|
+
chain: SolanaChain = "solana:mainnet",
|
|
354
|
+
): SolanaSigner {
|
|
355
|
+
const signer: SolanaSigner = {
|
|
356
|
+
address: account.address,
|
|
357
|
+
async signMessage(message) {
|
|
358
|
+
const feature = walletFeature<SolanaSignMessageFeature>(wallet, SolanaSignMessage);
|
|
359
|
+
const [output] = await feature.signMessage({ account, message });
|
|
360
|
+
return output.signature;
|
|
361
|
+
},
|
|
362
|
+
async signTransaction(transaction) {
|
|
363
|
+
const feature = walletFeature<SolanaSignTransactionFeature>(wallet, SolanaSignTransaction);
|
|
364
|
+
const [output] = await feature.signTransaction({ account, transaction, chain });
|
|
365
|
+
return output.signedTransaction;
|
|
366
|
+
},
|
|
367
|
+
};
|
|
368
|
+
if (wallet.features[SolanaSignAndSendTransaction]) {
|
|
369
|
+
signer.signAndSendTransaction = async (transaction) => {
|
|
370
|
+
const feature = walletFeature<SolanaSignAndSendTransactionFeature>(
|
|
371
|
+
wallet,
|
|
372
|
+
SolanaSignAndSendTransaction,
|
|
373
|
+
);
|
|
374
|
+
const [output] = await feature.signAndSendTransaction({ account, transaction, chain });
|
|
375
|
+
return output.signature;
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
return signer;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/** The Wallet Standard signer for a wallet that already holds `owner`, or null. */
|
|
382
|
+
export function findSolanaSigner(owner: string, chain?: SolanaChain): SolanaSigner | null {
|
|
383
|
+
for (const wallet of getSolanaWallets()) {
|
|
384
|
+
const account = wallet.accounts.find((a) => a.address === owner);
|
|
385
|
+
if (account) return standardSolanaSigner(wallet, account, chain);
|
|
386
|
+
}
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Connect a Wallet Standard Solana wallet without the modal. `wallet` picks one
|
|
392
|
+
* by name (case-insensitive); otherwise the first registered one is used.
|
|
393
|
+
*/
|
|
394
|
+
export async function connectSolanaWallet(
|
|
395
|
+
options: { wallet?: string; chain?: SolanaChain; silent?: boolean } = {},
|
|
396
|
+
): Promise<SolanaSigner> {
|
|
397
|
+
const wallets = getSolanaWallets();
|
|
398
|
+
const wallet = options.wallet
|
|
399
|
+
? wallets.find((w) => w.name.toLowerCase() === options.wallet?.toLowerCase())
|
|
400
|
+
: wallets[0];
|
|
401
|
+
if (!wallet) {
|
|
402
|
+
throw new Error(
|
|
403
|
+
options.wallet
|
|
404
|
+
? `No Solana wallet named ${options.wallet} is installed`
|
|
405
|
+
: "No Solana wallet found. Install Phantom, Solflare or Backpack.",
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
const { accounts } = await walletFeature<StandardConnectFeature>(wallet, StandardConnect).connect(
|
|
409
|
+
{ silent: options.silent },
|
|
410
|
+
);
|
|
411
|
+
const chain = options.chain ?? "solana:mainnet";
|
|
412
|
+
const account = accounts.find((a) => a.chains.includes(chain)) ?? accounts[0];
|
|
413
|
+
if (!account) throw new Error(`${wallet.name} returned no Solana account`);
|
|
414
|
+
return standardSolanaSigner(wallet, account, chain);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const utf8 = (bytes: Uint8Array): string | null => {
|
|
418
|
+
try {
|
|
419
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
420
|
+
} catch {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* The signer behind a wallet connected through the modal's injected Solana
|
|
427
|
+
* adapter. Text messages go through the adapter exactly as login always has;
|
|
428
|
+
* transactions and non-text messages go through the Wallet Standard wallet
|
|
429
|
+
* holding the same address.
|
|
430
|
+
*/
|
|
431
|
+
export function injectedSolanaSigner(
|
|
432
|
+
adapter: Pick<WalletAdapter, "address" | "signMessage">,
|
|
433
|
+
chain?: SolanaChain,
|
|
434
|
+
): SolanaSigner {
|
|
435
|
+
const owner = adapter.address;
|
|
436
|
+
if (!owner) throw new Error("injectedSolanaSigner: connect a Solana wallet first");
|
|
437
|
+
const standard = (method: string): SolanaSigner => {
|
|
438
|
+
const signer = findSolanaSigner(owner, chain);
|
|
439
|
+
if (!signer) {
|
|
440
|
+
throw new UnsupportedClientMethodError(
|
|
441
|
+
"solana",
|
|
442
|
+
method,
|
|
443
|
+
`no Wallet Standard wallet holds ${owner}; connect Phantom, Solflare or Backpack`,
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
return signer;
|
|
447
|
+
};
|
|
448
|
+
return {
|
|
449
|
+
address: owner,
|
|
450
|
+
async signMessage(message) {
|
|
451
|
+
const text = utf8(message);
|
|
452
|
+
if (text === null) return standard("signMessage").signMessage(message);
|
|
453
|
+
return Uint8Array.from(getBase58Encoder().encode(await adapter.signMessage(text)));
|
|
454
|
+
},
|
|
455
|
+
signTransaction: async (transaction) =>
|
|
456
|
+
standard("signTransaction").signTransaction(transaction),
|
|
457
|
+
async signAndSendTransaction(transaction) {
|
|
458
|
+
const signer = standard("signAndSendTransaction");
|
|
459
|
+
if (!signer.signAndSendTransaction) {
|
|
460
|
+
throw new UnsupportedClientMethodError("solana", "signAndSendTransaction");
|
|
461
|
+
}
|
|
462
|
+
return signer.signAndSendTransaction(transaction);
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { WalletAdapter } from "../connectkit/adapters/types";
|
|
2
|
+
import type { ChainClient, ClientCapability } from "./types";
|
|
3
|
+
|
|
4
|
+
export type SolanaCluster = "mainnet" | "devnet" | "testnet" | "localnet";
|
|
5
|
+
/** The Wallet Standard chain id a wallet signs for. */
|
|
6
|
+
export type SolanaChain = `solana:${SolanaCluster}`;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A Solana wallet that only signs messages, over the modal's adapter. It needs
|
|
10
|
+
* no @solana/kit, which is why sign-in uses it: the full client (transactions,
|
|
11
|
+
* RPC) is `useSolanaClient()` from `@multiplatform.one/web3/solana`.
|
|
12
|
+
*/
|
|
13
|
+
export interface SolanaMessageClient extends ChainClient<"solana"> {
|
|
14
|
+
readonly address: string;
|
|
15
|
+
readonly chainId: SolanaChain;
|
|
16
|
+
/** base58 ed25519 signature over the UTF-8 message. */
|
|
17
|
+
signMessage(message: string): Promise<string>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const capabilities: readonly ClientCapability[] = ["signMessage"];
|
|
21
|
+
|
|
22
|
+
export function solanaMessageClient(
|
|
23
|
+
adapter: Pick<WalletAdapter, "address" | "signMessage">,
|
|
24
|
+
chain: SolanaChain = "solana:mainnet",
|
|
25
|
+
): SolanaMessageClient {
|
|
26
|
+
if (!adapter.address) throw new Error("solanaMessageClient: connect a Solana wallet first");
|
|
27
|
+
return {
|
|
28
|
+
family: "solana",
|
|
29
|
+
address: adapter.address,
|
|
30
|
+
chainId: chain,
|
|
31
|
+
capabilities,
|
|
32
|
+
signMessage: (message) => adapter.signMessage(message),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { WalletAdapter } from "../connectkit/adapters/types";
|
|
2
|
+
import { UnsupportedClientMethodError, type ChainClient, type ClientCapability } from "./types";
|
|
3
|
+
|
|
4
|
+
type MessageAdapter = Pick<WalletAdapter, "address" | "signMessage">;
|
|
5
|
+
|
|
6
|
+
const txTodo =
|
|
7
|
+
"needs @mysten/sui's Transaction plus the wallet's sui:signTransaction / sui:signAndExecuteTransaction features";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Sui client. Message signing only, over the connected Sui adapter. The
|
|
11
|
+
* transaction methods are the shape the transaction work will fill in; until
|
|
12
|
+
* then they reject with UnsupportedClientMethodError.
|
|
13
|
+
*/
|
|
14
|
+
export interface SuiClient extends ChainClient<"sui"> {
|
|
15
|
+
readonly address: string;
|
|
16
|
+
readonly chainId: "sui:mainnet";
|
|
17
|
+
/** Sui's serialized signature (flag || signature || public key), base64. */
|
|
18
|
+
signMessage(message: string): Promise<string>;
|
|
19
|
+
/** Not implemented yet: will take a built transaction and return `{ bytes, signature }`. */
|
|
20
|
+
signTransaction(transaction: unknown): Promise<never>;
|
|
21
|
+
/** Not implemented yet: will return the executed transaction digest. */
|
|
22
|
+
signAndExecuteTransaction(transaction: unknown): Promise<never>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const capabilities: readonly ClientCapability[] = ["signMessage"];
|
|
26
|
+
|
|
27
|
+
export function suiClient(adapter: MessageAdapter): SuiClient {
|
|
28
|
+
if (!adapter.address) throw new Error("suiClient: connect a Sui wallet first");
|
|
29
|
+
return {
|
|
30
|
+
family: "sui",
|
|
31
|
+
address: adapter.address,
|
|
32
|
+
chainId: "sui:mainnet",
|
|
33
|
+
capabilities,
|
|
34
|
+
signMessage: (message) => adapter.signMessage(message),
|
|
35
|
+
signTransaction: async () => {
|
|
36
|
+
throw new UnsupportedClientMethodError("sui", "signTransaction", txTodo);
|
|
37
|
+
},
|
|
38
|
+
signAndExecuteTransaction: async () => {
|
|
39
|
+
throw new UnsupportedClientMethodError("sui", "signAndExecuteTransaction", txTodo);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Ecosystem } from "@multiplatform.one/connectkit";
|
|
2
|
+
|
|
3
|
+
/** Who signs: the four wallet ecosystems, plus a GPG key. */
|
|
4
|
+
export type ClientFamily = Ecosystem | "gpg";
|
|
5
|
+
|
|
6
|
+
export type ClientCapability =
|
|
7
|
+
| "signMessage"
|
|
8
|
+
| "signTransaction"
|
|
9
|
+
| "sendTransaction"
|
|
10
|
+
| "signAndSendTransaction"
|
|
11
|
+
| "writeContract";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The shape every per-chain client shares. `signMessage` returns the family's
|
|
15
|
+
* native signature encoding, which is what the Keycloak verifiers take as the
|
|
16
|
+
* login `username`: EVM 0x hex, Solana base58, Sui base64 serialized signature,
|
|
17
|
+
* Bitcoin base64 BIP-322, GPG the armored signature followed by the armored
|
|
18
|
+
* public key.
|
|
19
|
+
*/
|
|
20
|
+
export interface ChainClient<F extends ClientFamily = ClientFamily> {
|
|
21
|
+
readonly family: F;
|
|
22
|
+
/** Chain-native address. Null for GPG, whose identity arrives with the signature. */
|
|
23
|
+
readonly address: string | null;
|
|
24
|
+
/** EVM numeric chain id, or a CAIP-2 style id (`solana:mainnet`, `sui:mainnet`, `bitcoin`). */
|
|
25
|
+
readonly chainId?: number | string;
|
|
26
|
+
readonly capabilities: readonly ClientCapability[];
|
|
27
|
+
signMessage(message: string): Promise<string>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** A client method the family does not implement yet. */
|
|
31
|
+
export class UnsupportedClientMethodError extends Error {
|
|
32
|
+
constructor(
|
|
33
|
+
readonly family: ClientFamily,
|
|
34
|
+
readonly method: string,
|
|
35
|
+
detail?: string,
|
|
36
|
+
) {
|
|
37
|
+
super(`${family} client: ${method} is not supported${detail ? ` (${detail})` : ""}`);
|
|
38
|
+
this.name = "UnsupportedClientMethodError";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useContext, useMemo } from "react";
|
|
2
|
+
import { useAccount } from "wagmi";
|
|
3
|
+
import { Web3ConfigContext } from "../providers/walletConfig";
|
|
4
|
+
import { connectorAdapter } from "./adapter";
|
|
5
|
+
import {
|
|
6
|
+
injectedSolanaSigner,
|
|
7
|
+
solanaChainFromRpcUrl,
|
|
8
|
+
solanaClient,
|
|
9
|
+
type SolanaChain,
|
|
10
|
+
type SolanaClient,
|
|
11
|
+
} from "./solana";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The connected Solana wallet as an mpo Solana client: message signing through
|
|
15
|
+
* the modal's adapter, transactions through the Wallet Standard wallet holding
|
|
16
|
+
* the same address, reads and sends over `Web3Config.solanaRpcUrl`.
|
|
17
|
+
*/
|
|
18
|
+
export function useSolanaClient(
|
|
19
|
+
options: { rpcUrl?: string; chain?: SolanaChain } = {},
|
|
20
|
+
): SolanaClient | undefined {
|
|
21
|
+
const { connector, address } = useAccount();
|
|
22
|
+
const config = useContext(Web3ConfigContext);
|
|
23
|
+
const rpcUrl = options.rpcUrl ?? config?.solanaRpcUrl;
|
|
24
|
+
const chain = options.chain ?? solanaChainFromRpcUrl(rpcUrl);
|
|
25
|
+
return useMemo(() => {
|
|
26
|
+
const adapter = connectorAdapter(connector, "solana");
|
|
27
|
+
if (!adapter?.address) return undefined;
|
|
28
|
+
return solanaClient({ signer: injectedSolanaSigner(adapter, chain), rpcUrl, chain });
|
|
29
|
+
// address is a dependency so an account switch inside one connector rebuilds the client
|
|
30
|
+
}, [connector, address, rpcUrl, chain]);
|
|
31
|
+
}
|