@stacks/connect
[!NOTE]
Please be patient during this latest migration.
There has been a long-running effort together with wallets to modernize and move forward the Stacks web ecosystem.
It is now culminating in SIP-030 and the new request
method in Stacks Connect 8.x.x
.
Bear with us during this migration.
Wallets are still working through some bugs, details, and improvements.
We're working on it!
Feel free to continue using Stacks Connect 7.x.x
while things stabilize.
The 7.x.x
version may still be more well supported by some wallets.
For the legacy version of @stacks/connect
using JWT tokens, please use the following command:
npm install @stacks/connect@7.10.1
π¬ Migration Guide
Welcome to the new Stacks Connect! β¨ Read the @stacks/connect
docs for more information.
For a while now the Stacks community has been working on a new standard for wallet-to-dapp communication.
Stacks Connect and related projects now use standards like WBIPs and SIP-030 to allow wallets to communicate with dapps in a more simplified and flexible way.
β οΈ Deprecations
The following classes, methods, and types are deprecated in favor of the new request
RPC methods:
show...
and open...
methodsauthenticate
methodUserSession
class and related functionalityAppConfig
classSessionOptions
interfaceSessionData
interfaceUserData
interfaceSessionDataStore
classInstanceDataStore
classLocalStorageStore
class
[!NOTE]
To make migrating easier, the familiar UserSession
& AppConfig
class still exists and is semi-backwards compatible for the 8.x.x
release.
It will "cache" the user's address in local storage and allow access to it via the loadUserData
method (as previously done).
βΆοΈ Migration Steps
To update from <=7.x.x
to latest/8.x.x
, follow these steps.
- Update your
@stacks/connect
version:
npm install @stacks/connect@latest
- Switch from
showXyz
, openXyz
, doXyz
methods to the request
method.
request
follows the pattern request(method: string, params: object)
, see Usage for more detailsrequest
is an async function, so replace the onFinish
and onCancel
callbacks with .then().catch()
or try & await
- e.g.,
showConnect()
, authenticate()
β connect()
- e.g.,
useConnect().doContractCall({})
β request("stx_callContract", {})
- e.g.,
openContractDeploy()
β request("stx_deployContract", {})
-
Switch from showConnect
orauthenticate
to connect()
methods
connect()
is an alias for request({forceWalletSelect: true}, 'getAddresses')
connect()
by default caches the user's address in local storage
-
Switch from UserSession.isSignedIn()
to isConnected()
-
Switch from UserSession.signUserOut()
to disconnect()
-
Remove code referencing deprecated methods (AppConfig
, UserSession
, etc.)
-
Remove the @stacks/connect-react
package.
- You may need to manually reload a component to see local storage updates.
- No custom hooks are needed to use Stacks Connect anymore.
- We are working on a new
@stacks/react
package that will make usage even easier in the future (e.g. tracking transaction status, reloading components when a connection is established, updating the page when the network changes, and more).
πͺͺ Address Access
Previously, the UserSession
class was used to access the user's addresses and data, which abstracted away the underlying implementation details.
Now, the request
method is used to directly interact with the wallet, giving developers more explicit control and clarity over what's happening under the hood.
This manual approach makes the wallet interaction more transparent and customizable.
Developer can manually manage the currently connected user's address in e.g. local storage, jotai, etc. or use the connect()
/request()
method to cache the address in local storage.
[!IMPORTANT]
For security reasons, the 8.x.x
release only returns the current network's address (where previously both mainnet and testnet addresses were returned).
Usage
Try the Connect Method Demo App π to see which methods/features are available for wallets
Install @stacks/connect
npm install @stacks/connect
pnpm install @stacks/connect
yarn add @stacks/connect
Connect to a wallet
Initiate a wallet connection and request addresses.
import { connect } from '@stacks/connect';
const response = await connect();
Get the local storage data (stored by a connect
call).
import { getLocalStorage } from '@stacks/connect';
const data = getLocalStorage();
Managing the connection state.
import { connect, disconnect, isConnected } from '@stacks/connect';
isConnected();
await connect();
isConnected();
disconnect();
isConnected();
Use request
to trigger wallet interactions
import { request } from '@stacks/connect';
const response = await request({ forceWalletSelect: true }, 'getAddresses');
Available methods
getAddresses
const response = await request('getAddresses');
sendTransfer
const response = await request('sendTransfer', {
recipients: [
{
address: 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4',
amount: '1000',
},
{
address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
amount: '2000',
},
],
});
signPsbt
const response = await request('signPsbt', {
psbt: 'cHNidP...',
signInputs: [{ index: 0, address }],
broadcast: false,
});
stx_getAddresses
const response = await request('stx_getAddresses');
stx_getAccounts
const response = await request('stx_getAccounts');
stx_transferStx
const response = await request('stx_transferStx', {
amount: '1000',
recipient: 'SP2MF04VAGYHGAZWGTEDW5VYCPDWWSY08Z1QFNDSN',
network: 'mainnet',
memo: 'Optional memo',
});
stx_callContract
const response = await request('stx_callContract', {
contract: 'SP2MF04VAGYHGAZWGTEDW5VYCPDWWSY08Z1QFNDSN.counters',
functionName: 'count',
functionArgs: [Cl.int(3)],
network: 'mainnet',
});
stx_deployContract
const response = await request('stx_deployContract', {
name: 'counters',
clarityCode: `(define-map counters principal int)
(define-public (count (change int))
(ok (map-set counters tx-sender (+ (get-count tx-sender) change)))
)
(define-read-only (get-count (who principal))
(default-to 0 (map-get? counters who))
)`,
clarityVersion: '2',
network: 'mainnet',
});
stx_signMessage
const response = await request('stx_signMessage', {
message: 'Hello, World!',
});
stx_signStructuredMessage
const clarityMessage = Cl.parse('{ structured: "message", num: u3 }');
const clarityDomain = Cl.tuple({
domain: Cl.stringAscii('example.com'),
version: Cl.stringAscii('1.0.0'),
'chain-id': Cl.uint(1),
});
const response = await request('stx_signStructuredMessage', {
message: clarityMessage,
domain: clarityDomain,
});
Error Handling
The request
method returns a Promise, allowing you to handle errors using standard Promise-based error handling patterns. You can use either try/catch
with async/await
or the .catch()
method with Promise chains.
Using try/catch with async/await
import { request } from '@stacks/connect';
try {
const response = await request('stx_transferStx', {
amount: '1000',
recipient: 'SP2MF04VAGYHGAZWGTEDW5VYCPDWWSY08Z1QFNDSN',
});
console.log('Transaction successful:', response.txid);
} catch (error) {
console.error('Wallet returned an error:', error);
}
Compatibility
The request
method by default adds a layer of auto-compatibility for different wallet providers.
This is meant to unify the interface where wallet providers may not implement methods and results the same way.
Method | | Notes |
---|
getAddresses | π΅ | Maps to wallet_connect for Xverse-like wallets |
sendTransfer | π΅ | Converts amount to number for Xverse, string for Leather |
signPsbt | π‘ | Transforms PSBT format for Leather (base64 to hex) with lossy restructure of signInputs |
stx_getAddresses | π΅ | Maps to wallet_connect for Xverse-like wallets |
stx_getAccounts | π’ | |
stx_getNetworks | π’ | |
stx_transferStx | π’ | |
stx_transferSip10Ft | π’ | |
stx_transferSip9Nft | π’ | |
stx_callContract | π΅ | Transforms Clarity values to hex-encoded format for compatibility |
stx_deployContract | π΅ | Transforms Clarity values to hex-encoded format for compatibility |
stx_signTransaction | π΅ | Transforms Clarity values to hex-encoded format for compatibility |
stx_signMessage | π΅ | Transforms Clarity values to hex-encoded format for compatibility |
stx_signStructuredMessage | π΅ | Transforms Clarity values to hex-encoded format for compatibility |
stx_updateProfile | π’ | |
stx_accountChange (event) | π’ | |
stx_networkChange (event) | π’ | |
- π’ No overrides needed for any wallet
- π΅ Has compatibility overrides that maintain functionality
- π‘ Has breaking overrides that may lose some information
To disable this behavior, you can set the enableOverrides
option to false
or use the requestRaw
method detailed below.
Advanced Usage
request
The request
method is called with an optional options object as the first parameter:
import { request } from '@stacks/connect';
const response = await request(
{
provider?: StacksProvider;
forceWalletSelect?: boolean;
persistWalletSelect?: boolean;
enableOverrides?: boolean;
enableLocalStorage?: boolean;
defaultProviders?: WbipProvider[];
approvedProviderIds?: string[];
},
'method',
params
);
const response = await request('method', params);
The enableOverrides
option enables automatic compatibility fixes for different wallet providers.
For example, it handles converting numeric types between string and number formats as needed by different wallets, and remaps certain method names to match wallet-specific implementations.
This ensures consistent behavior across different wallet providers without requiring manual adjustments.
The approvedProviderIds
option allows you to filter which wallet providers are shown in the connect modal.
This is useful when you want to limit the available wallet options to specific providers.
For example, you might only want to support Leather wallet:
connect({ approvedProviderIds: ['LeatherProvider'] });
Or multiple specific wallets:
connect({ approvedProviderIds: ['LeatherProvider', 'xverse'] });
requestRaw
The requestRaw
method provides direct access to wallet providers without the additional features of request
:
import { requestRaw } from '@stacks/connect';
const response = await requestRaw(provider, 'method', params);
Note: requestRaw
bypasses the UI wallet selector, automatic provider compatibility fixes, and other features that come with request
.
Use this when you need more manual control over the wallet interaction process.
Support
Here's a list of methods and events that are supported by popular wallets:
Method | Leather | Xverse-like |
---|
getAddresses | π‘ No support for experimental purposes | π‘ Use wallet_connect instead |
sendTransfer | π‘ Expects amount as string | π‘ Expects amount as number |
signPsbt | π‘ Uses signing index array only | π‘ Uses signInputs record instead of array |
stx_getAddresses | π’ | π΄ |
stx_getAccounts | π΄ | π’ |
stx_getNetworks | π΄ | π΄ |
stx_transferStx | π’ | π’ |
stx_transferSip10Ft | π’ | π΄ |
stx_transferSip9Nft | π’ | π΄ |
stx_callContract | π‘ Hex-encoded Clarity values only | π‘ Hex-encoded Clarity values only, no support for postConditions |
stx_deployContract | π‘ Hex-encoded Clarity values only | π‘ Hex-encoded Clarity values only, no support for postConditions |
stx_signTransaction | π‘ Hex-encoded Clarity values only | π‘ Hex-encoded Clarity values only |
stx_signMessage | π‘ Hex-encoded Clarity values only | π‘ Hex-encoded Clarity values only |
stx_signStructuredMessage | π‘ Hex-encoded Clarity values only | π‘ Hex-encoded Clarity values only |
stx_updateProfile | π΄ | π΄ |
Event | Leather | Xverse |
---|
stx_accountChange | π΄ | π΄ |
stx_networkChange | π΄ | π΄ |
- π΄ No support (yet)
- π‘ Partial support
- π’ Supported