# Generate signers

## Generate signers

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

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

**Examples:**[**​**](https://docs.x.immutable.com/docs/x/how-to-generate-signers#examples)

| ✅ Require user signatures                                                                                                                                                                                                     | ❌ Do not require user signatures                                          |                                                                                                                                                                                                                        |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p>Transactions that update<br>blockchain state</p>                                                                                                                                                                           | <p>Operations requiring user<br>authorization</p>                         | <mark style="color:blue;">Read-only operations</mark>                                                                                                                                                                  |
| <ul><li>Creating an order</li><li>Filling an order (creating a trade)</li><li>Transferring assets between users</li><li>Depositing assets on L2 (XpansionChain)</li><li>Withdrawing assets to L1 (Layer 1 Ethereum)</li></ul> | <ul><li>Creating a project</li><li>Registering a user off-chain</li></ul> | <ul><li>Getting a list of all assets on XpansionChain</li><li>Getting the details (ie. metadata) of a particular asset</li><li>Getting a list of all open orders</li><li>Getting a list of historical trades</li></ul> |

#### Using "signers" to get user signatures[​](https://docs.x.immutable.com/docs/x/how-to-generate-signers#using-signers-to-get-user-signatures) <a href="#using-signers-to-get-user-signatures" id="using-signers-to-get-user-signatures"></a>

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?[​](https://docs.x.immutable.com/docs/x/how-to-generate-signers#how-do-applications-generate-and-use-signers) <a href="#how-do-applications-generate-and-use-signers" id="how-do-applications-generate-and-use-signers"></a>

There are two ways to get signers in your application:

1. <mark style="color:blue;">**Generate your own by obtaining and using the user's private keys**</mark>
2. <mark style="color:blue;">**Connect to a user's wallet application**</mark>

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[​](https://docs.x.immutable.com/docs/x/how-to-generate-signers#1-generate-your-own-signers) <a href="#id-1-generate-your-own-signers" id="id-1-generate-your-own-signers"></a>

💡AVAILABLE WITH:

* <mark style="color:blue;">Core SDK</mark>

#### Core SDK[​](https://docs.x.immutable.com/docs/x/how-to-generate-signers#core-sdk) <a href="#core-sdk" id="core-sdk"></a>

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.

* Typescript Core SDK

The Core SDK provides functionality for applications to generate Stark (L2) <mark style="color:blue;">private keys</mark> and <mark style="color:blue;">signers</mark>:

```
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);
```

* Kotlin (JVM) Core SDK

In order to use any workflow functions, you will need to pass in the connected wallet provider. This means you will need to implement your own Wallet L1 <mark style="color:blue;">Signer</mark>.

Once you have created a Signer instance you can generate the user's Stark key pair and use it to create an instance of StandardStarkSigner, an implementation of StarkSigner.

```
StarkKey.generate(signer).whenComplete { keyPair, error ->
    val starkSigner = StandardStarkSigner(keyPair)
}
```

* Swift Core SDK

In order to use any workflow functions, you will need to pass in the connected wallet provider. This means you will need to implement your own Wallet L1 <mark style="color:blue;">Signer</mark> and L2 <mark style="color:blue;">StarkSigner</mark>.

Once you have a Signer instance you can generate the user's Stark key pair and use the result to instantiate a StarkSigner, for example, by using the default StandardStarkSigner provided by the SDK.

```
let keyPair = try await StarkKey.generateKeyPair(from: signer)
let starkSigner = StandardStarkSigner(pair: keyPair)
```

* Golang Core SDK

#### 1. Generate L1 signer[​](https://docs.x.immutable.com/docs/x/how-to-generate-signers#1-generate-l1-signer) <a href="#id-1-generate-l1-signer" id="id-1-generate-l1-signer"></a>

When you implement an L1signer, it must satisfy <mark style="color:blue;">L1Signer interface</mark>. See <mark style="color:blue;">BaseL1Signer</mark> for a sample implementation of an L1 Signer.

Also refer to <mark style="color:blue;">examples/publicapi/list\_assets/main.go</mark> for environment setup examples.

#### 2. Generate L2 signer[​](https://docs.x.immutable.com/docs/x/how-to-generate-signers#2-generate-l2-signer) <a href="#id-2-generate-l2-signer" id="id-2-generate-l2-signer"></a>

See <mark style="color:blue;">signers/stark</mark> for information about generating your own L2 signer, as well as the following code snippet:

```
import (
   "github.com/XpansionChain/imx-core-sdk-golang/signers/stark"
   ...
)

func main() {
   // L1 credentials
   l1signer := YourImplementationOfL1SignerInterface() // See examples/workflows/utils/signer.go

   // L2 credentials
   // Obtain the stark signer associated with this user.
   l2signer, err := stark.GenerateStarkSigner(l1signer) // this is the sdk helper function
   if err != nil {
      ...
   }
}
```

### 2. Connect to users' wallets[​](https://docs.x.immutable.com/docs/x/how-to-generate-signers#2-connect-to-users-wallets) <a href="#id-2-connect-to-users-wallets" id="id-2-connect-to-users-wallets"></a>

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

* Wallet SDK

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

| Wallet SDK                                          | Platform | Wallets supported                                             |
| --------------------------------------------------- | -------- | ------------------------------------------------------------- |
| <mark style="color:blue;">Wallet SDK Web</mark>     | Web      | <ul><li>Metamask</li><li>WalletConnect</li></ul>              |
| <mark style="color:blue;">Wallet SDK Android</mark> | Android  | <ul><li>Any wallet that supports WalletConnect v1.0</li></ul> |
| <mark style="color:blue;">Wallet SDK iOS</mark>     | iOS      | <ul><li>Any wallet that supports WalletConnect v1.0</li></ul> |

* Wallet SDK Web

1. Install the <mark style="color:blue;">Wallet SDK npm package</mark>:

```
npm install @imtbl/wallet-sdk-web --save
```

2. Set up the Wallet SDK and use with the <mark style="color:blue;">Core SDK for Typescript</mark>:

```
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;
  }
);
```

* Wallet SDK Android

1. Add Maven Central and JitPack to your repositories

```
repositories {
    mavenCentral()
    maven { url = "https://jitpack.io" } // Needed for WalletConnect
}
```

2. Add the dependency to your app's `build.gradle` file:

```
dependencies {
    implementation 'com.XpansionChain.wallet:imx-wallet-sdk-android:$version'
}
```

3. In your `Application` class:

```
class ExampleApplication : Application() {
  override fun onCreate() {
    super.onCreate()
   XpansionChainXWallet.init(this)
  }
}
```

4. Connect to the user's wallet

```
XpansionChainXWallet.connect(
    Provider.WalletConnect(
        appUrl = "https://www.marketplace.com/",
        appName = "My NFT Marketplace",
        appDescription = "This is a marketplace where all my favorite NFTs can be traded.",
        appIcons = listOf("http://www.marketplace.com/appicon.svg")
    )
)
```

If you want to use your own bridge server instead of the default provide it via bridgeServerUrl when connecting. For more info on how WalletConnect and the bridge works <mark style="color:blue;">see here</mark>.

5. Use with the <mark style="color:blue;">Core SDK for Kotlin/JVM</mark>

Once you connect a user's wallet with the Wallet SDK you can provide the `Signer` and `StarkSigner` instances to Core SDK workflows:

```
val signer = XpansionChainXWallet.signer
val starkSigner = XpansionChainXWallet.starkSigner
if (signer != null && starkSigner != null) {
    XpansionChainXCore.buy(orderId, emptyList(), signer, starkSigner).whenComplete { ... }
} else {
    // Handle not connected
}
```

* Wallet SDK iOS

1. Add `pod` XpansionChain`XWallet` to your Podfile

```
platform :ios, '13.0'
use_frameworks!

target 'MyApp' do
  pod 'XpansionChainXWallet'
end
```

2. Connect to the user's wallet

```
try await XpansionChainXWallet.shared.connect(
    to: .walletConnect(
        config: .init(
            appURL: URL(string: "https://XpansionChain.com")!,
            appName: "XpansionChain Sample",
            // The Universal Link or URL Scheme of the chosen wallet to be connected.
            walletDeeplink: "https://metamask.app.link"
        )
    )
)
```

If you want to use your own bridge server instead of the default provide it via bridgeServerUrl when connecting. For more info on how WalletConnect and the bridge works <mark style="color:blue;">see here</mark>.

3. Use with the <mark style="color:blue;">Core SDK for Swift</mark>

Once you connect a user's wallet with the Wallet SDK you can provide the `Signer` and `StarkSigner` instances to Core SDK workflows:

```
guard let signer = XpansionChainWallet.shared.signer,
    let starkSigner = XpansionChainWallet.shared.starkSigner else {
    // handle not connected
    return
}

let result = try await XpansionChainCore.shared.buy(
    orderId: orderId,
    signer: signer,
    starkSigner: starkSigner
)
```

* Link SDK

1. Install the <mark style="color:blue;">npm package</mark>:

```
npm install @imtbl/imx-sdk --save
# or
yarn add @imtbl/imx-sdk
```

2. Import the Link package:

```
import { Link } from '@imtbl/imx-sdk';
```

3. Set the correct network URL

Choose from the following:

| Network    | Description                                        | URL                                                                            |
| ---------- | -------------------------------------------------- | ------------------------------------------------------------------------------ |
| Sandbox    | The default test network (currently, it is Goërli) | <mark style="color:blue;"><https://link.sandbox.x.XpansionChain.com/v1></mark> |
| Production | Ethereum network                                   | <mark style="color:blue;"><https://link.x.XpansionChain.com/v1></mark>         |

```
const linkAddress = 'https://link.x.XpansionChain.com/v1'; // Or "https://link.sandbox.x.immutable.com/v1"
```

4. Initialize the client

```
const link = new Link(linkAddress);
```

Operations like registering a user (see <mark style="color:blue;">guide</mark>) can be executed by the Link client, which uses the JS SDK under the hood.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xpansionchain-1.gitbook.io/xpansionchain/guides/basic-guides/generate-signers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
