Generate Key Pairs And Fund
The "Generate Key Pairs" component allows users to generate new Stellar Wallet key pairs. The Wallet is funded by friendbot on the Stellar Testnet. A trustline for a custom asset is established upon wallet generation.
The component includes fields for displaying the generated wallet address and secret key. Along with information on the status of the wallet creation and trustline establishment.
Bonus: This component can establish a trustline for a custom asset upon wallet generation.
Features
- Generates new Stellar Wallet key pairs.
- Displays the generated wallet address and secret key.
- Establishes a trustline for a custom Stellar asset upon wallet generation.
- Provides a user-friendly interface for generating wallet key pairs and immediately establishing custom asset trustlines.
Configuration
- Install the Stellar SDK Version required for your project. We are using and recommend the latest Protocol 20 supported SDK.
- Open the HorizonServer.js file and update the
assetCode
&distributionWalletPk
variables with your custom assets information.
Additional Resources
Stellar employs public key cryptography for secure transactions. Each Stellar account has a keypair containing a public key and a secret key. The public key is shareable and used by others to identify your account and verify authorized transactions, similar to an email address. In contrast, the secret key is private and acts like a password, providing ownership and access to your account. It should never be shared with anyone to maintain account security.
Friendbot is a bot that funds accounts with fake XLM on Testnet or Futurenet. You can request XLM from Friendbot using the Stellar Laboratory or with various SDKs. Requests to Friendbot are rate limited, so use it wisely. Friendbot provides 10,000 fake XLM when funding a new account.
If you are creating multiple accounts, you can fund your first account with Friendbot and then use that first account to fund your subsequent accounts using the Create Account operation.
C#
COMING SOON via NuGet Package Implementation v1.0.1
Javascript
We've provided simple HTML and JavaScript that can be used in your project as partial-components or be customized and integrated into your existing codebase.
*Current Version as of 2024-24-02*
<script src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/11.2.2/stellar-sdk.js"></script>
<script language="javascript">
var statusArea;
var keyPair = null;
document.addEventListener("DOMContentLoaded", async function () {
statusArea = document.getElementById('trustlineStatus');
// Define the loadAccountData function
async function loadAccountData(accountId) {
try {
const account = await horizonServer.loadAccount(accountId);
return account;
} catch (error) {
console.error('Error loading account data:', error);
throw error;
}
}
// Function to load account data with delay
async function loadAccountWithDelay(accountId, maxAttempts = 10, interval = 1000) {
let attempts = 0;
let account;
while (attempts < maxAttempts) {
// Wait for a short interval before the next attempt
await new Promise(resolve => setTimeout(resolve, interval));
attempts++;
try {
// Attempt to load the account
account = await loadAccountData(accountId);
// Exit the loop if successful
if (account) {
break;
}
} catch (loadError) {
console.warn('Error loading account data (attempt ' + (attempts + 1) + '):', loadError);
}
}
return account;
}
async function establishTrustline(secretKey, publicKey) {
console.log('Attempting to establish trustline for public key:', publicKey);
// Check if the wallet address is generated
if (publicKey) {
try {
// Fund the wallet with Friendbot if not funded already
await fundWithFriendbot(publicKey);
// Attempt to load the account with a delay
const account = await loadAccountWithDelay(publicKey);
// Log the loaded account data
console.log('Loaded account data:', account);
// Ensure that the account has a balance
if (account.balances && account.balances.length > 0) {
// Trustline operation
const trustlineOperation = StellarSdk.Operation.changeTrust({
asset: new StellarSdk.Asset(assetCode, distributionWalletPk),
});
// Get the current sequence from the loaded account
const sequence = account.sequence;
// Transaction
const transaction = new StellarSdk.TransactionBuilder(account, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
sequence: sequence, // Ensure sequence is used correctly
})
.addOperation(trustlineOperation)
.setTimeout(0)
.build();
// Sign the transaction
transaction.sign(StellarSdk.Keypair.fromSecret(secretKey));
// Submit the transaction
const result = await horizonServer.submitTransaction(transaction);
console.log('Trustline established successfully:', result);
try {
if (null != hostTargetElement) {
hostTargetElement.style.display = "block";
}
} catch (error) {
console.error('hostTargetElement not defined ', error);
}
} else {
console.error('Account does not have a balance. Unable to establish trustline.');
}
} catch (error) {
console.error('Error establishing trustline:', error);
if (error.response && error.response.data) {
console.log('Trustline response data:', error.response.data);
if (error.response.data.extras) {
console.log('Trustline extras:', error.response.data.extras);
}
}
}
} else {
// Prompt the user to sign to establish the trustline
// You can implement the logic for user interaction or use a modal/popup
console.log('User needs to sign to establish trustline');
// Add your code for user interaction here
}
}
// Event listener for the Generate Wallet Button
document.getElementById('generateWalletBtn').addEventListener('click', async function () {
// disable the hosting form's submit button if defined
try {
if (null != hostTargetElement) {
hostTargetElement.style.display = "none";
}
} catch (error) {
console.error('hostTargetElement not defined ', error);
}
// Use the Stellar SDK to generate a new key pair
keyPair = await generateKeypair();
// Display the generated keys to the user
document.getElementById('WalletAddress').value = keyPair.publicKey;
document.getElementById('GeneratedSecretKey').value = keyPair.secret;
// Show the new wallet info section
document.getElementById('newWalletInfo').style.display = 'block';
// Check if the wallet address is generated and establish trustline accordingly
if (keyPair) {
await establishTrustline(keyPair.secret, keyPair.publicKey);
}
});
});
</script>
<div id="GenerateKeyPair">
<!-- Existing Wallet Address Field -->
<div>
<label for="WalletAddress">Wallet Address:</label>
<div class="flex items-center border-b border-white">
<input required type="text" id="WalletAddress" name="WalletAddress" class="block rounded-md border-none focus:ring-2 focus:ring-inset focus:ring-indigo-600" />
</div>
</div>
<!-- Generate New Stellar Wallet Button -->
<div>
<button type="button" name="generateWalletBtn" id="generateWalletBtn" class="group relative">
Generate New Stellar Wallet
</button>
</div>
<!-- New Wallet Info Section -->
<div id="newWalletInfo">
<div>
<label for="GeneratedSecretKey">Generated Secret Key:</label>
<input type="text" id="GeneratedSecretKey" name="GeneratedSecretKey" class="block w-full rounded-md border border-indigo-700 focus:ring-2 focus:ring-inset focus:ring-indigo-600" />
</div>
<p id="trustlineStatus" class="text-red-500"><strong>Important:</strong> Copy and Save the secret key securely. It will not be transmitted to stored or servers and cannot be recovered.</p>
</div>
</div>