Skip to main content

Generate signers

User signatures are required for certain types of operations on ImmutableX. These are:

  1. Transactions that update blockchain state
  2. Operations that update ImmutableX's databases that require user authorization for

Examples:

✅ Require user signatures❌ Do not require user signatures
Transactions that update
blockchain state
Operations requiring user
authorization
Read-only operations
  • Creating an order
  • Filling an order (creating a trade)
  • Transferring assets between users
  • Depositing assets on L2 (ImmutableX)
  • Withdrawing assets to L1 (Layer 1 Ethereum)
  • Creating a project
  • Registering a user off-chain
  • Getting a list of all assets on ImmutableX
  • Getting the details (ie. metadata) of a particular asset
  • Getting a list of all open orders
  • Getting a list of historical trades

Using "signers" to get user signatures

In order to get user signatures, applications can use "signers". These are abstractions of user accounts that can be used to sign transactions. A user's private key is required to generate them.

Ethereum (L1) signers are required to sign transactions on L1 (ie. depositing assets from the L1 wallet to the L2 one) and Stark (L2) signers are required to sign transactions on L2 (ie. creating an order on an L2 marketplace, transferring an asset to another user on L2).

How do applications generate and use signers?

There are two ways to get signers in your application:

  1. Generate your own by obtaining and using the user's private keys
  2. Connect to a user's wallet application

The first option, where an application obtains a user's private key directly, is risky because these keys allow anyone in possession of them full control of an account.

The second option provides an application with an interface to the user's account by prompting the user to connect with their wallet application (ie. mobile or browser wallet). Once connected the app can begin asking the user to sign transactions and messages without having to reveal their private key.

1. Generate your own signers

📝Available with:

Core SDK

Below are instructions on how to generate:

  • Ethereum (L1) signers
  • Stark (L2) private keys and signers using the Core SDK
caution

If you generate your own Stark private key, you will have to persist it. The key is randomly generated so cannot be deterministically re-generated.

The Core SDK provides functionality for applications to generate Stark (L2) private keys and signers:

import { AlchemyProvider } from '@ethersproject/providers';
import { Wallet } from '@ethersproject/wallet';
import { generateStarkPrivateKey, createStarkSigner } from '@imtbl/core-sdk';

// Create Ethereum signer
const ethNetwork = 'goerli'; // Or 'mainnet'
const provider = new AlchemyProvider(ethNetwork, YOUR_ALCHEMY_API_KEY);
const ethSigner = new Wallet(YOUR_PRIVATE_ETH_KEY).connect(provider);

// Create Stark signer
const starkPrivateKey = generateStarkPrivateKey(); // Or retrieve previously generated key
const starkSigner = createStarkSigner(starkPrivateKey);

2. Connect to users' wallets

Your application can facilitate signing of user transactions by connecting to users' wallet applications. This ensures that you do not have to handle private keys.

📝Available with:
  • Wallet SDK (with Core SDK)
  • Link SDK

The Wallet SDK provides a way for applications to connect to certain user wallets:

Wallet SDKPlatformWallets supported
Wallet SDK WebWeb
  • Metamask
  • WalletConnect
Wallet SDK AndroidAndroid
  • Any wallet that supports WalletConnect v1.0
Wallet SDK iOSiOS
  • Any wallet that supports WalletConnect v1.0
  1. Install the Wallet SDK npm package:
npm install @imtbl/wallet-sdk-web --save
  1. Set up the Wallet SDK and use with the Core SDK for Typescript:
import {
ENVIRONMENTS,
L1_PROVIDERS,
WalletSDK,
} from '@imtbl/wallet-sdk-web';

(async () => {
// Builds the Wallet SDK object
const sdk = await WalletSDK.build({
env: ENVIRONMENTS.STAGING,
/*
RPC config is only required if the WalletConnect provider (L1_PROVIDERS.WALLET_CONNECT)
is being used. Follow this reference for the RPC config:
https://docs.walletconnect.com/quick-start/dapps/web3-provider#provider-options
*/
rpc: {
5: 'https://goerli.mycustomnode.com',
},
/*
Will switch the chain based on this configured chainID when connecting to the wallet.(Optional)
Following the table below to get the chainID and name mapping.
Consult https://chainlist.org/ for more.
ChainId | Network
--- --- | --- ---
1 | Ethereum Main Network (Mainnet)
5 | Goerli Test Network
*/
chainID: 5,
});

// Connects on the chosen provider - WalletConnect
const walletConnection = await sdk.connect({ provider: L1_PROVIDERS.WALLET_CONNECT });
// For Metamask:
// const walletConnection = await sdk.connect({ provider: L1_PROVIDERS.METAMASK });

// Use with the Core SDK for Typescript, e.g. Register a user
await client.registerOffchain(walletConnection);
})();
tip

The WalletConnection object can also be retrieved in the following ways:

// By calling the method `getWalletConnection`
const walletConnection = sdk.getWalletConnection();

// By listening to the event `WALLET_SDK_EVENTS.CONNECTION_UPDATED`
walletSdkEvents.on(
WALLET_SDK_EVENTS.CONNECTION_UPDATED,
(updatedWalletConnection: WalletConnection) =>
{ const walletConnection = updatedWalletConnection; },
);