Generate signers
Generate signers
User signatures are required for certain types of operations on XpansionChain. These are:
Transactions that update blockchain state
Operations that update XpansionChain's databases that require user authorization for
Examples:
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 (XpansionChain)
Withdrawing assets to L1 (Layer 1 Ethereum)
Creating a project
Registering a user off-chain
Getting a list of all assets on XpansionChain
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:
Generate your own by obtaining and using the user's private keys
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
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.
Typescript Core SDK
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);
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 Signer.
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 Signer and L2 StarkSigner.
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
When you implement an L1signer, it must satisfy L1Signer interface. See BaseL1Signer for a sample implementation of an L1 Signer.
Also refer to examples/publicapi/list_assets/main.go for environment setup examples.
2. Generate L2 signer
See signers/stark 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
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 Web
Web
Metamask
WalletConnect
Wallet SDK Android
Android
Any wallet that supports WalletConnect v1.0
Wallet SDK iOS
iOS
Any wallet that supports WalletConnect v1.0
Wallet SDK Web
Install the Wallet SDK npm package:
npm install @imtbl/wallet-sdk-web --save
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;
}
);
Wallet SDK Android
Add Maven Central and JitPack to your repositories
repositories {
mavenCentral()
maven { url = "https://jitpack.io" } // Needed for WalletConnect
}
Add the dependency to your app's
build.gradle
file:
dependencies {
implementation 'com.XpansionChain.wallet:imx-wallet-sdk-android:$version'
}
In your
Application
class:
class ExampleApplication : Application() {
override fun onCreate() {
super.onCreate()
XpansionChainXWallet.init(this)
}
}
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 see here.
Use with the Core SDK for Kotlin/JVM
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
Add
pod
XpansionChainXWallet
to your Podfile
platform :ios, '13.0'
use_frameworks!
target 'MyApp' do
pod 'XpansionChainXWallet'
end
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 see here.
Use with the Core SDK for Swift
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
Install the npm package:
npm install @imtbl/imx-sdk --save
# or
yarn add @imtbl/imx-sdk
Import the Link package:
import { Link } from '@imtbl/imx-sdk';
Set the correct network URL
Choose from the following:
Sandbox
The default test network (currently, it is Goërli)
https://link.sandbox.x.XpansionChain.com/v1
Production
Ethereum network
https://link.x.XpansionChain.com/v1
const linkAddress = 'https://link.x.XpansionChain.com/v1'; // Or "https://link.sandbox.x.immutable.com/v1"
Initialize the client
const link = new Link(linkAddress);
Operations like registering a user (see guide) can be executed by the Link client, which uses the JS SDK under the hood.
Last updated