@metamask/connect-solana 1.1.0 → 2.0.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/CHANGELOG.md +23 -1
- package/README.md +19 -8
- package/dist/browser/es/connect-solana.mjs +32 -6
- package/dist/browser/es/connect-solana.mjs.map +1 -1
- package/dist/node/cjs/connect-solana.js +30 -6
- package/dist/node/cjs/connect-solana.js.map +1 -1
- package/dist/node/es/connect-solana.mjs +32 -6
- package/dist/node/es/connect-solana.mjs.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/package.json +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Validate `@metamask/connect-multichain` peer version at runtime and warn on mismatch ([#253](https://github.com/MetaMask/connect-monorepo/pull/253))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **BREAKING:** `@metamask/connect-multichain` is now a peer dependency.
|
|
19
|
+
Add it to your own `dependencies` (e.g. `npm install @metamask/connect-multichain`)
|
|
20
|
+
— it is no longer installed transitively.
|
|
21
|
+
- Bump workspace dependencies:
|
|
22
|
+
- @metamask/connect-multichain@1.0.0
|
|
23
|
+
|
|
24
|
+
## [1.2.0]
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- Add an `analytics.enabled` option to `createSolanaClient()`. Set it to `false` to disable dapp-side analytics events and wallet correlation metadata. ([#303](https://github.com/MetaMask/connect-monorepo/pull/303))
|
|
29
|
+
|
|
10
30
|
## [1.1.0]
|
|
11
31
|
|
|
12
32
|
### Changed
|
|
@@ -93,7 +113,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
93
113
|
|
|
94
114
|
- Initial Release
|
|
95
115
|
|
|
96
|
-
[Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@
|
|
116
|
+
[Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@2.0.0...HEAD
|
|
117
|
+
[2.0.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@1.2.0...@metamask/connect-solana@2.0.0
|
|
118
|
+
[1.2.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@1.1.0...@metamask/connect-solana@1.2.0
|
|
97
119
|
[1.1.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@1.0.0...@metamask/connect-solana@1.1.0
|
|
98
120
|
[1.0.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@0.8.1...@metamask/connect-solana@1.0.0
|
|
99
121
|
[0.8.1]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@0.8.0...@metamask/connect-solana@0.8.1
|
package/README.md
CHANGED
|
@@ -102,19 +102,30 @@ Creates a new Solana client instance. By default, the wallet is automatically re
|
|
|
102
102
|
|
|
103
103
|
#### Parameters
|
|
104
104
|
|
|
105
|
-
| Option
|
|
106
|
-
|
|
|
107
|
-
| `dapp.name`
|
|
108
|
-
| `dapp.url`
|
|
109
|
-
| `dapp.iconUrl`
|
|
110
|
-
| `api.supportedNetworks`
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
105
|
+
| Option | Type | Required | Description |
|
|
106
|
+
| --------------------------- | ------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
107
|
+
| `dapp.name` | `string` | Yes | Name of your dApp |
|
|
108
|
+
| `dapp.url` | `string` | No | URL of your dApp |
|
|
109
|
+
| `dapp.iconUrl` | `string` | No | Icon URL for your dApp |
|
|
110
|
+
| `api.supportedNetworks` | `SolanaSupportedNetworks` | No | Map of network names (`mainnet`, `devnet`, `testnet`) to RPC URLs |
|
|
111
|
+
| `analytics.enabled` | `boolean` | No | Enables dapp-side analytics. Defaults to `true`; set to `false` to disable analytics events and wallet correlation metadata. |
|
|
112
|
+
| `analytics.integrationType` | `string` | No | Integration type for analytics |
|
|
113
|
+
| `debug` | `boolean` | No | Reserved for future use; not currently forwarded to the underlying client |
|
|
114
|
+
| `skipAutoRegister` | `boolean` | No | Skip auto-registering the wallet during creation (defaults to `false`) |
|
|
113
115
|
|
|
114
116
|
#### Returns
|
|
115
117
|
|
|
116
118
|
`Promise<SolanaClient>`
|
|
117
119
|
|
|
120
|
+
```typescript
|
|
121
|
+
const client = await createSolanaClient({
|
|
122
|
+
dapp: {
|
|
123
|
+
name: 'My Solana DApp',
|
|
124
|
+
url: 'https://mydapp.com',
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
118
129
|
---
|
|
119
130
|
|
|
120
131
|
### `getInfuraRpcUrls(options)`
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
/* Browser ES build */
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
2
21
|
var __async = (__this, __arguments, generator) => {
|
|
3
22
|
return new Promise((resolve, reject) => {
|
|
4
23
|
var fulfilled = (value) => {
|
|
@@ -72,6 +91,7 @@ import {
|
|
|
72
91
|
getWalletStandard,
|
|
73
92
|
registerSolanaWalletStandard
|
|
74
93
|
} from "@metamask/solana-wallet-standard";
|
|
94
|
+
import { satisfies } from "semver";
|
|
75
95
|
|
|
76
96
|
// src/utils.ts
|
|
77
97
|
import {
|
|
@@ -89,7 +109,7 @@ var isMetamaskExtensionRegistered = () => {
|
|
|
89
109
|
// src/connect.ts
|
|
90
110
|
function createSolanaClient(options) {
|
|
91
111
|
return __async(this, null, function* () {
|
|
92
|
-
var _a, _b, _c, _d, _e;
|
|
112
|
+
var _a, _b, _c, _d, _e, _f;
|
|
93
113
|
const defaultNetworks = {
|
|
94
114
|
mainnet: "https://api.mainnet-beta.solana.com"
|
|
95
115
|
};
|
|
@@ -102,16 +122,22 @@ function createSolanaClient(options) {
|
|
|
102
122
|
api: {
|
|
103
123
|
supportedNetworks
|
|
104
124
|
},
|
|
105
|
-
analytics: {
|
|
125
|
+
analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
|
|
106
126
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
107
|
-
integrationType: ((
|
|
108
|
-
},
|
|
127
|
+
integrationType: ((_e = options.analytics) == null ? void 0 : _e.integrationType) || "direct"
|
|
128
|
+
}),
|
|
109
129
|
versions: {
|
|
110
130
|
// typeof guard needed: Metro (React Native) bundles TS source directly,
|
|
111
131
|
// bypassing the tsup build that substitutes __PACKAGE_VERSION__.
|
|
112
|
-
"connect-solana": false ? "unknown" : "
|
|
132
|
+
"connect-solana": false ? "unknown" : "2.0.0"
|
|
113
133
|
}
|
|
114
134
|
});
|
|
135
|
+
const multichainClientPeerRange = false ? "unknown" : "^1.0.0";
|
|
136
|
+
if (multichainClientPeerRange !== "unknown" && multichainClientPeerRange !== "" && !satisfies(core.version, multichainClientPeerRange)) {
|
|
137
|
+
console.warn(
|
|
138
|
+
`@metamask/connect-solana expected @metamask/connect-multichain version ${multichainClientPeerRange}, but got ${core.version}. This may lead to unexpected behavior.`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
115
141
|
const client = core.provider;
|
|
116
142
|
const walletName = "MetaMask";
|
|
117
143
|
let hasRegisteredMmc = false;
|
|
@@ -144,7 +170,7 @@ function createSolanaClient(options) {
|
|
|
144
170
|
}
|
|
145
171
|
const provider = getWalletStandard({ client, walletName });
|
|
146
172
|
const session = yield core.provider.getSession();
|
|
147
|
-
const hasSolanaScope = Object.keys((
|
|
173
|
+
const hasSolanaScope = Object.keys((_f = session == null ? void 0 : session.sessionScopes) != null ? _f : {}).some(
|
|
148
174
|
(scope) => scope.startsWith("solana:")
|
|
149
175
|
);
|
|
150
176
|
if (hasSolanaScope) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,oBAAoB,kCAAkC;;;ACMxD,IAAM,kBAAiD;AAAA,EAC5D,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAQO,SAAS,sBACd,UACwB;AACxB,SAAO,OAAO,QAAQ,QAAQ,EAAE;AAAA,IAC9B,CAAC,KAAK,CAAC,SAAS,MAAM,MAAM;AAC1B,YAAM,SAAS,gBAAgB,OAAwB;AACvD,UAAI,UAAU,QAAQ;AACpB,YAAI,MAAM,IAAI;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AACF;;;ADfO,IAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AACF,MAG+B;AAC7B,QAAM,eAAe,SAAS;AAAA,IAC5B,CAAC,YAAY,gBAAgB,OAAO;AAAA,EACtC;AACA,QAAM,UAAU,2BAA2B;AAAA,IACzC;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,SAAS,OAAgC,CAAC,KAAK,YAAY;AAChE,UAAM,SAAS,gBAAgB,OAAO;AACtC,UAAM,SAAS,QAAQ,MAAM;AAC7B,QAAI,QAAQ;AACV,UAAI,OAAO,IAAI;AAAA,IACjB;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AACP;;;AEtCA;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;;;ACRP;AAAA,EACE;AAAA,EACA,eAAe;AAAA,OACV;AACP,SAAS,kBAAkB;AAE3B,IAAM,YAAY;AAGX,IAAM,SAAS,aAAa,WAAW,IAAI;AAY3C,IAAM,gCAAgC,MAAe;AAC1D,QAAM,UAAU,WAAW;AAE3B,SAAO,QACJ,IAAI,EACJ,KAAK,CAAC,WAAW,OAAO,KAAK,YAAY,EAAE,SAAS,UAAU,CAAC;AACpE;;;ADiCA,SAAsB,mBACpB,SACuB;AAAA;AA9DzB;AA+DE,UAAM,kBAA2C;AAAA,MAC/C,SAAS;AAAA,IACX;AAEA,UAAM,oBAAmB,aAAQ,qBAAR,YAA4B;AAErD,UAAM,oBAAoB;AAAA,OACxB,mBAAQ,QAAR,mBAAa,sBAAb,YAAkC;AAAA,IACpC;AAEA,UAAM,OAAO,MAAM,uBAAuB;AAAA,MACxC,MAAM,QAAQ;AAAA,MACd,KAAK;AAAA,QACH;AAAA,MACF;AAAA,MACA,WAAW;AAAA;AAAA,QAET,mBAAiB,aAAQ,cAAR,mBAAmB,oBAAmB;AAAA,MACzD;AAAA,MACA,UAAU;AAAA;AAAA;AAAA,QAGR,kBACE,QACI,YACA;AAAA,MACR;AAAA,IACF,CAAC;AAED,UAAM,SAAS,KAAK;AAEpB,UAAM,aAAa;AAEnB,QAAI,mBAAmB;AACvB,QAAI;AACJ,UAAM,iCAAiC,IAAI,QAAc,CAAC,YAAY;AACpE,gCAA0B;AAAA,IAC5B,CAAC;AAED,UAAM,iBAAiB,MAA2B;AAChD,UAAI,kBAAkB;AACpB,eAAO,qDAAqD;AAC5D;AAAA,MACF;AAEA,UAAI,8BAA8B,GAAG;AACnC,eAAO,uDAAuD;AAC9D;AAAA,MACF;AAEA,YAAM,6BAA6B,EAAE,QAAQ,WAAW,CAAC;AACzD,yBAAmB;AAAA,IACrB;AAEA,QAAI,kBAAkB;AACpB,8BAAwB;AAAA,IAC1B,OAAO;AAEL,iBAAW,MAAY;AACrB,YAAI;AACF,gBAAM,eAAe;AAAA,QACvB,UAAE;AACA,kCAAwB;AAAA,QAC1B;AAAA,MACF,IAAG,GAAI;AAAA,IACT;AAEA,UAAM,WAAW,kBAAkB,EAAE,QAAQ,WAAW,CAAC;AACzD,UAAM,UAAU,MAAM,KAAK,SAAS,WAAW;AAC/C,UAAM,iBAAiB,OAAO,MAAK,wCAAS,kBAAT,YAA0B,CAAC,CAAC,EAAE;AAAA,MAC/D,CAAC,UAAU,MAAM,WAAW,SAAS;AAAA,IACvC;AACA,QAAI,gBAAgB;AAElB,YAAM,SAAS,SAAS,kBAAkB,EAAE,QAAQ;AAAA,IACtD;AAEA,WAAO;AAAA,MACL;AAAA,MACA,WAAW,MAAM;AAAA,MACjB,gBAAgB,MAA2B;AACzC,cAAM;AACN,cAAM,eAAe;AAAA,MACvB;AAAA,MACA,YAAY,MAAS;AACnB,qBAAM,KAAK,WAAW,OAAO,OAAO,eAAe,CAAY;AAAA;AAAA,IACnE;AAAA,EACF;AAAA;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ and __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__ are esbuild define conventions */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\nimport { satisfies } from 'semver';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Values substituted by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\ndeclare const __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.enabled] - Whether to enable dapp-side analytics (defaults to true)\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n ...(options.analytics ?? {}),\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const multichainClientPeerRange =\n typeof __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__ === 'undefined'\n ? 'unknown'\n : __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__;\n\n if (\n multichainClientPeerRange !== 'unknown' &&\n multichainClientPeerRange !== '' &&\n !satisfies(core.version, multichainClientPeerRange)\n ) {\n console.warn(\n `@metamask/connect-solana expected @metamask/connect-multichain version ${multichainClientPeerRange}, but got ${core.version}. This may lead to unexpected behavior.`,\n );\n }\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
/* Node.js CJS build */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defProps = Object.defineProperties;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
7
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
9
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
11
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __spreadValues = (a, b) => {
|
|
13
|
+
for (var prop in b || (b = {}))
|
|
14
|
+
if (__hasOwnProp.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
if (__getOwnPropSymbols)
|
|
17
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
18
|
+
if (__propIsEnum.call(b, prop))
|
|
19
|
+
__defNormalProp(a, prop, b[prop]);
|
|
20
|
+
}
|
|
21
|
+
return a;
|
|
22
|
+
};
|
|
23
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
7
24
|
var __export = (target, all) => {
|
|
8
25
|
for (var name in all)
|
|
9
26
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -93,6 +110,7 @@ var getInfuraRpcUrls = ({
|
|
|
93
110
|
// src/connect.ts
|
|
94
111
|
var import_connect_multichain3 = require("@metamask/connect-multichain");
|
|
95
112
|
var import_solana_wallet_standard = require("@metamask/solana-wallet-standard");
|
|
113
|
+
var import_semver = require("semver");
|
|
96
114
|
|
|
97
115
|
// src/utils.ts
|
|
98
116
|
var import_connect_multichain2 = require("@metamask/connect-multichain");
|
|
@@ -107,7 +125,7 @@ var isMetamaskExtensionRegistered = () => {
|
|
|
107
125
|
// src/connect.ts
|
|
108
126
|
function createSolanaClient(options) {
|
|
109
127
|
return __async(this, null, function* () {
|
|
110
|
-
var _a, _b, _c, _d, _e;
|
|
128
|
+
var _a, _b, _c, _d, _e, _f;
|
|
111
129
|
const defaultNetworks = {
|
|
112
130
|
mainnet: "https://api.mainnet-beta.solana.com"
|
|
113
131
|
};
|
|
@@ -120,16 +138,22 @@ function createSolanaClient(options) {
|
|
|
120
138
|
api: {
|
|
121
139
|
supportedNetworks
|
|
122
140
|
},
|
|
123
|
-
analytics: {
|
|
141
|
+
analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
|
|
124
142
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
125
|
-
integrationType: ((
|
|
126
|
-
},
|
|
143
|
+
integrationType: ((_e = options.analytics) == null ? void 0 : _e.integrationType) || "direct"
|
|
144
|
+
}),
|
|
127
145
|
versions: {
|
|
128
146
|
// typeof guard needed: Metro (React Native) bundles TS source directly,
|
|
129
147
|
// bypassing the tsup build that substitutes __PACKAGE_VERSION__.
|
|
130
|
-
"connect-solana": false ? "unknown" : "
|
|
148
|
+
"connect-solana": false ? "unknown" : "2.0.0"
|
|
131
149
|
}
|
|
132
150
|
});
|
|
151
|
+
const multichainClientPeerRange = false ? "unknown" : "^1.0.0";
|
|
152
|
+
if (multichainClientPeerRange !== "unknown" && multichainClientPeerRange !== "" && !(0, import_semver.satisfies)(core.version, multichainClientPeerRange)) {
|
|
153
|
+
console.warn(
|
|
154
|
+
`@metamask/connect-solana expected @metamask/connect-multichain version ${multichainClientPeerRange}, but got ${core.version}. This may lead to unexpected behavior.`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
133
157
|
const client = core.provider;
|
|
134
158
|
const walletName = "MetaMask";
|
|
135
159
|
let hasRegisteredMmc = false;
|
|
@@ -162,7 +186,7 @@ function createSolanaClient(options) {
|
|
|
162
186
|
}
|
|
163
187
|
const provider = (0, import_solana_wallet_standard.getWalletStandard)({ client, walletName });
|
|
164
188
|
const session = yield core.provider.getSession();
|
|
165
|
-
const hasSolanaScope = Object.keys((
|
|
189
|
+
const hasSolanaScope = Object.keys((_f = session == null ? void 0 : session.sessionScopes) != null ? _f : {}).some(
|
|
166
190
|
(scope) => scope.startsWith("solana:")
|
|
167
191
|
);
|
|
168
192
|
if (hasSolanaScope) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/index.ts","../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["export { getInfuraRpcUrls } from './infura';\nexport { createSolanaClient } from './connect';\nexport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaNetwork,\n SolanaSupportedNetworks,\n} from './types';\n","import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":["getInfuraRpcUrlsMultichain","import_connect_multichain","import_connect_multichain"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/index.ts","../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["export { getInfuraRpcUrls } from './infura';\nexport { createSolanaClient } from './connect';\nexport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaNetwork,\n SolanaSupportedNetworks,\n} from './types';\n","import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ and __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__ are esbuild define conventions */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\nimport { satisfies } from 'semver';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Values substituted by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\ndeclare const __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.enabled] - Whether to enable dapp-side analytics (defaults to true)\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n ...(options.analytics ?? {}),\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const multichainClientPeerRange =\n typeof __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__ === 'undefined'\n ? 'unknown'\n : __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__;\n\n if (\n multichainClientPeerRange !== 'unknown' &&\n multichainClientPeerRange !== '' &&\n !satisfies(core.version, multichainClientPeerRange)\n ) {\n console.warn(\n `@metamask/connect-solana expected @metamask/connect-multichain version ${multichainClientPeerRange}, but got ${core.version}. This may lead to unexpected behavior.`,\n );\n }\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":["getInfuraRpcUrlsMultichain","import_connect_multichain","import_connect_multichain"]}
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
/* Node.js ES build */
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
2
21
|
var __async = (__this, __arguments, generator) => {
|
|
3
22
|
return new Promise((resolve, reject) => {
|
|
4
23
|
var fulfilled = (value) => {
|
|
@@ -72,6 +91,7 @@ import {
|
|
|
72
91
|
getWalletStandard,
|
|
73
92
|
registerSolanaWalletStandard
|
|
74
93
|
} from "@metamask/solana-wallet-standard";
|
|
94
|
+
import { satisfies } from "semver";
|
|
75
95
|
|
|
76
96
|
// src/utils.ts
|
|
77
97
|
import {
|
|
@@ -89,7 +109,7 @@ var isMetamaskExtensionRegistered = () => {
|
|
|
89
109
|
// src/connect.ts
|
|
90
110
|
function createSolanaClient(options) {
|
|
91
111
|
return __async(this, null, function* () {
|
|
92
|
-
var _a, _b, _c, _d, _e;
|
|
112
|
+
var _a, _b, _c, _d, _e, _f;
|
|
93
113
|
const defaultNetworks = {
|
|
94
114
|
mainnet: "https://api.mainnet-beta.solana.com"
|
|
95
115
|
};
|
|
@@ -102,16 +122,22 @@ function createSolanaClient(options) {
|
|
|
102
122
|
api: {
|
|
103
123
|
supportedNetworks
|
|
104
124
|
},
|
|
105
|
-
analytics: {
|
|
125
|
+
analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
|
|
106
126
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
107
|
-
integrationType: ((
|
|
108
|
-
},
|
|
127
|
+
integrationType: ((_e = options.analytics) == null ? void 0 : _e.integrationType) || "direct"
|
|
128
|
+
}),
|
|
109
129
|
versions: {
|
|
110
130
|
// typeof guard needed: Metro (React Native) bundles TS source directly,
|
|
111
131
|
// bypassing the tsup build that substitutes __PACKAGE_VERSION__.
|
|
112
|
-
"connect-solana": false ? "unknown" : "
|
|
132
|
+
"connect-solana": false ? "unknown" : "2.0.0"
|
|
113
133
|
}
|
|
114
134
|
});
|
|
135
|
+
const multichainClientPeerRange = false ? "unknown" : "^1.0.0";
|
|
136
|
+
if (multichainClientPeerRange !== "unknown" && multichainClientPeerRange !== "" && !satisfies(core.version, multichainClientPeerRange)) {
|
|
137
|
+
console.warn(
|
|
138
|
+
`@metamask/connect-solana expected @metamask/connect-multichain version ${multichainClientPeerRange}, but got ${core.version}. This may lead to unexpected behavior.`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
115
141
|
const client = core.provider;
|
|
116
142
|
const walletName = "MetaMask";
|
|
117
143
|
let hasRegisteredMmc = false;
|
|
@@ -144,7 +170,7 @@ function createSolanaClient(options) {
|
|
|
144
170
|
}
|
|
145
171
|
const provider = getWalletStandard({ client, walletName });
|
|
146
172
|
const session = yield core.provider.getSession();
|
|
147
|
-
const hasSolanaScope = Object.keys((
|
|
173
|
+
const hasSolanaScope = Object.keys((_f = session == null ? void 0 : session.sessionScopes) != null ? _f : {}).some(
|
|
148
174
|
(scope) => scope.startsWith("solana:")
|
|
149
175
|
);
|
|
150
176
|
if (hasSolanaScope) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ and __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__ are esbuild define conventions */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\nimport { satisfies } from 'semver';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Values substituted by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\ndeclare const __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.enabled] - Whether to enable dapp-side analytics (defaults to true)\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n ...(options.analytics ?? {}),\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const multichainClientPeerRange =\n typeof __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__ === 'undefined'\n ? 'unknown'\n : __CONNECT_MULTICHAIN_PEER_VERSION_RANGE__;\n\n if (\n multichainClientPeerRange !== 'unknown' &&\n multichainClientPeerRange !== '' &&\n !satisfies(core.version, multichainClientPeerRange)\n ) {\n console.warn(\n `@metamask/connect-solana expected @metamask/connect-multichain version ${multichainClientPeerRange}, but got ${core.version}. This may lead to unexpected behavior.`,\n );\n }\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":[]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -85,6 +85,7 @@ declare const getInfuraRpcUrls: ({ infuraApiKey, networks, }: {
|
|
|
85
85
|
* @param options.api - Optional API configuration with supported networks
|
|
86
86
|
* @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs
|
|
87
87
|
* @param [options.analytics] - Analytics configuration
|
|
88
|
+
* @param [options.analytics.enabled] - Whether to enable dapp-side analytics (defaults to true)
|
|
88
89
|
* @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')
|
|
89
90
|
* @param options.debug - Enable debug logging
|
|
90
91
|
* @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/connect-solana",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Solana
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "MetaMask Connect Solana adapter — Wallet Standard integration over the multichain client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
7
7
|
"Solana"
|
|
@@ -58,14 +58,16 @@
|
|
|
58
58
|
"test:watch": "vitest watch"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@metamask/connect-multichain": "^0.13.0",
|
|
62
61
|
"@metamask/solana-wallet-standard": "^0.6.0",
|
|
63
62
|
"@wallet-standard/app": "~1.1.0",
|
|
64
|
-
"@wallet-standard/base": "^1.1.0"
|
|
63
|
+
"@wallet-standard/base": "^1.1.0",
|
|
64
|
+
"semver": "^7.7.4"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@metamask/auto-changelog": "^3.4.4",
|
|
68
|
+
"@metamask/connect-multichain": "^1.0.0",
|
|
68
69
|
"@types/jsdom": "^21.1.7",
|
|
70
|
+
"@types/semver": "^7.7.1",
|
|
69
71
|
"@vitest/coverage-v8": "^3.2.4",
|
|
70
72
|
"jsdom": "^26.1.0",
|
|
71
73
|
"prettier": "^3.3.3",
|
|
@@ -75,6 +77,9 @@
|
|
|
75
77
|
"typescript": "^5.9.3",
|
|
76
78
|
"vitest": "^3.1.2"
|
|
77
79
|
},
|
|
80
|
+
"peerDependencies": {
|
|
81
|
+
"@metamask/connect-multichain": "^1.0.0"
|
|
82
|
+
},
|
|
78
83
|
"engines": {
|
|
79
84
|
"node": ">=20.19.0"
|
|
80
85
|
},
|