Skip to main content

Wallets

In this tutorial we'll be reviewing how to create, save, recreate, and use a wallet. When you perform a transaction, the SDK will sign the transaction and send it to the network. This cryptographic seal allows us to detect any modifications to your data. Additionally, it provides traceability to your wallet's activity. This is because all of your transactions will be linked to your wallet.

info

A wallet is used to create and sign transactions; also, the wallet will have a unique address. The nodes will perform validations of the signature and the wallet's existence in the blockchain for those transactions, so it's a requirement to use valid wallets when creating transactions.

info

This tutorial assumes that you have an existing blockchain set up with ULedger. For additional information, please visit Getting Started and Import ULedger SDK.

Create a Wallet

Creating a wallet with the SDK involves several steps. To begin, we need to generate a seed phrase, as shown in the code sample below. First, we create an instance of the ULedger Wallet Generator class. Then, we use this instance to call the getSeedWords method. Take note of the parameters: '24' specifies the length of the word list that will be returned (this number can be any integer between 12 and 24). The second parameter determines the language. The supported languages for this parameter are English ('en'), Spanish ('es'), Italian ('it'), French ('fr'), and Portuguese ('pt'). The method returns an array of strings.

// Required imports
import { ULedgerWalletGenerator } from '@uledger/uledger-sdk';
// Get Word list
const words = ULedgerWalletGenerator.getSeedWords(12, 'en');
info

It's crucial to safeguard your seed phrase; the user is responsible for keeping it secure. If it gets lost, there is no action we can take to retrieve it.

Always maintain a secure offline copy of your seed phrase. With it, you can recover your wallet at any time.

For more information on seed phrases and BIP39:

Seed Phrase BIP39

In the next step, we'll use the word list obtained from the previous code sample to determine our seed phrase and create a wallet. Please note that the array of words provided by the last function call is not yet your seed phrase. You have the option to select a subset of these words, rearrange their order, or use the array as it is. Your seed phrase will only be finalized upon the creation of the wallet. This process will be illustrated in the code sample below. You will first see the function call to generate the wallet. What we need to provide is the array of words (which will become your new seed phrase) and the language specification. The output is a data structure that constitutes the ULedger Wallet.

// Generate Wallet
const wallet = ULedgerWalletGenerator.generateWalletFromSeedWords(words, 'en');

Congratulations! You've created your first wallet with the SDK. In this section, we discussed how to generate a ULedgerWallet object. In the following section, we will explore how serialization and deserialization of wallets allow for storage, such as saving the wallet in the form of a JSON file.

Save a Wallet Locally

Now that we've created our wallet, we will use the SDK to store the wallet in a file. At this step, you have the option to store the wallet in either JSON format or an encrypted format.

Let's concentrate on the serialization process. The data type used to represent a ULedgerWallet during this process is a string, chosen for its ease of handling. To serialize the wallet into a string, we invoke the serialize method and pass the wallet as a parameter. Additionally, there's an optional parameter: a password. If you provide a password, the wallet file will be encrypted, enhancing its security.

info

If a password is used, the individual utilizing the SDK assumes complete ownership of choosing and managing that password. The SDK does not offer password management features such as storage or recovery. Should the password be lost, the SDK will be unable to deserialize the wallet, thus preventing access to it.

info

The encryption used behind the password is based on the Advanced Encryption Standard and Galois/Counter Mode using AES-256-GCM algorithm, More Details

// Required imports
import { ULedgerWalletFactory } from '@uledger/uledger-sdk';
// Using the wallet generated previously
const serializedWallet = ULedgerWalletFactory.serialize(wallet);
// If a password is chosen (please take the Important Note #1 into consideration)
// myPassword is in complete control and responsibility of the one using the SDK
const serializedWallet = ULedgerWalletFactory.serialize(wallet, myPassword);

Let's examine the code sample above. First, we create an instance of the wallet factory class. Then we use that class object to call the serialize method. For parameters, we pass in the wallet object that we created in the previous section. Additionally, we pass an empty string to indicate that we want the file in JSON format (unencrypted). If you prefer to encrypt your file, the process is identical, except you would include a real password as a parameter. Below is the code sample for writing the data to a .ukey file.

import { writeFileSync } from 'fs';
writeFileSync('my_wallet.ukey', serializedWallet);

Excellent! You have now saved your wallet file to your local device or server. Next, we'll review how to retrieve that file and use the deserialize method to load your wallet from the .ukey file back into program memory. Please take a look at the code sample below.

// Required Imports
import { readFileSync } from 'fs';

const serializedWallet = readFileSync(`my_wallet.ukey`).toString();
// If no password was set in the serialization process
const wallet = ULedgerWalletFactory.deserialize(serializedWallet);
// If there was a password in the serialization process
const wallet = ULedgerWalletFactory.deserialize(serializedWallet, myPassword);

The first step in this code sample is to read the file from your local device and extract its contents. After obtaining the data, it's passed into the deserialize method. To do this, you'll need the wallet factory class object that we created at the beginning of this section. The parameters for the deserialize method are as follows: first, you pass in the file content represented as a string (in this code sample, we perform the typecasting inline). The second parameter is the password for the wallet file, which is only necessary if your wallet file is encrypted—that is, if you assigned a password when we used the serialize method. The deserialize method returns a ULedger Wallet object.

Great job! In this section, we've used the Wallet Factory class to serialize and store our wallet, as well as to deserialize the wallet and load it into program memory. In the next section, we'll review how to use the wallet for interactions with the blockchain!

Wallet Usage

Before we can use our wallet to create transactions, we need to register it to a blockchain. This is being done in the code sample below. In order to run this block of code successfully, you need to make sure the blockchain id and node url are using actual values instead of placeholder values. The real values are avaliable through your account on the ULedger Portal.

// Placeholder values, replace them with the actual values
const blockchainId = 'MyBlockchainId1';
const nodeUrl = 'https://my.node1.uledger.io';
await wallet.registerWallet(blockchainId, nodeUrl);
// In this example, `wallet` is registered in MyBlockchainId1
// If for some reason, the wallet needs to be used also in MyBlockchainId2:
const anotherBlockchainId = 'MyBlockchainId2';
await wallet.registerWallet(anotherBlockchainId, nodeUrl);

Once you have registered your wallet with the blockchain you'll be connecting with, we can create our first transaction. The first step in this process is to create a session with the ULedger network. This can be seen in the code sample below. Please make sure to replace the placeholder values with real values avaliable through your account on the ULedger Portal.

// Placeholder values, replace them with the actual values
const nodeUrl = '{{Node-URL}}';
const nodeId = 'MyNodeId';
const atomicClockUrl = '{{ACS-URL}}';
const blockchainId = 'MyBlockchainId1';

// Creating transaction session:
const transactionSession = new ULedgerTransactionSession({
nodeUrl,
nodeId,
atomicClockUrl,
}, wallet); // The wallet created in the previous steps

Once we have the transaction session object, we can proceed to building our transaction. In the first part of this code sample we are creating the custom payload of our transaction. For more information on this step, please visit the Transactions page. Basically, this is where you put your custom data.

In the second half of this code sample, we are building the transaction. This is where you specify the blockchain, your payload, the payload type, and to address.

// Creating the transaction payload:
const transactionPayload = {
to: 'Another Wallet Address', // Hash for the public key hex representation
payloadType: ULedgerTransactionPayloadType.DATA, // Data transaction type
blockchainId,
payload: {
myMessage: 'Hello World!'
}
};

Finally, we have our transaction ready and need to upload it to the blockchain network. This is done in the code sample below. It's very simple, we pass in the transaction input created above and the return type is a minted transaction on the blockchain.

// Sending the Transaction
const transaction = await transactionSession.createTransaction(transactionPayload);

Great work! You've created the first transaction with your new wallet! Once the block has been minted your should be able to query it on our blockchain explorer.

Recreate Wallet from Seed Phrase

In this section, we'll be reviewing how to recreate a wallet from your seed phrase. Please examine the code sample below. For this to work successfully, you just need to create a string array with your seed phrase. Once that is done, you can pass your seed phrase in to Generate Wallet from Seed method. Additionally, you need to pass in the language being used for your word list. The response type will be a ULedger Wallet object.

const words =  ["gain", "alley", ... , "bean"];
const wallet = ULedgerWalletGenerator.generateWalletFromSeedWords(words, 'en');

🔎 Search Wallet Activity

info

This tutorial assumes that you have an existing blockchain set up with ULedger. For additional information, please visit Getting Started and Import ULedger SDK.

In this tutorial, we'll be using the BMS to query our wallet activity. This method will return two embedded json objects. One containing transactions that the wallet has sent and the other containing transactions that the wallet has received.

To execute this successfully, first we need to create a session with the bms. This is done in the code sample below. Please make sure to replace the bms url with a real service url. This url can be found through your account on the ULedger portal. For more information on how to create a session, please visit this page.

// Required imports
import { ULedgerBMSSession } from 'uledger-sdk';
// Create a new session
const session = new ULedgerBMSSession({
url: "{{MY_BMS_URL}}"
});

From there, we can use our wallet address to query our activity. this is done in the code sample below. Lets break down the parameters,

  • Blockchain Id: This is a string representation of your blockchain identifier.

  • Wallet Address: This is a string representation of your wallet address.

  • Limit: This value is used to set a pagination limit to your response.

  • Offset: This value is used to set a pagination offset to your response.

  • Sort: This value is used to indicate if you would like the response to be sorted by time.

  • Public: This value is used to indicate if your blockchain is public.

// Search terms - which blockchain and which user are we looking for?
const blockchainId = "{{blockchain id}}";
const userIdKeyword = "1b";
// Pagination parameters
const limit = 10;
const offset = 0;
const sort = true;
// Should we exclude the transactions' payloads?
const trim = true;
// Send the request
const history = await session.userHistory(blockchainId, userIdKeyword, limit, offset, sort, trim, false);
// Log the result
console.log(`Transactions FROM userIds matching '${userIdKeyword}':`);
console.log(history.from);
console.log(`\nTransactions TO userIds matching '${userIdKeyword}':`);
console.log(history.to);
© 2023 ULedger Inc. All rights reserved