Skip to content

Instantly share code, notes, and snippets.

THE GOAL: Add Jade Hardware Wallet support to Nexus. Jade firmware has been forked to add support for Litecoin + Litecoin MWEB. We have created a NitroModule to interact with the Jade HW in React Native: react-native-nitro-jade (project directory: /Users/loshan/Repos/ltc/react-native-nitro-jade - directory also includes an example app in example/).

react-native-nitro-lndltc supports walletKitImportAccount & walletKitImportMwebScanKey. ImportAccount should be used to import the hardware wallet's HD public key (as watch only), which ImportMwebScanKey should import the hardware wallet's MWEB Scan Key.

Example of walletKitImportMwebScanKey (retrieve scan key, spend pubkey and master key fingerprint from jade hw):

lncli wallet accounts import-mweb-scan-key \
  --name "hw-mweb" \
  --scan_key c6fe1782af72a1987cf87cb7a8fbcfbecefb1d441f46366a90bdb0028e4a502a \
 --spend_pubkey 039fed1f844e48f3aa146f91b0ca0e31f6846d8f11efa518b75c2ca8f7fe352ba9 \
package psbt
import (
"bytes"
"encoding/base64"
"fmt"
"testing"
)
// TestVerifyHandCheck decodes the post-fix Jade-signed PSBT and checks
--- Waiting for the device to reconnect
I (450) esp_image: segment 4: paddr=001f08ac vaddr=403781d4 size=0b420h ( 46112) load
I (461) esp_image: segment 5: paddr=001fbcd4 vaddr=50000000 size=0001ch (    28) load
I (469) boot: Loaded app from partition at offset 0x10000
I (469) boot: Disabling RNG early entropy source...
I (480) octal_psram: vendor id    : 0x0d (AP)
I (480) octal_psram: dev id       : 0x02 (generation 3)
I (480) octal_psram: density      : 0x03 (64 Mbit)
I (482) octal_psram: good-die     : 0x01 (Pass)
/**
* MWEB Fee Calculator for Litecoin
* Based on Litecoin Core implementation (v0.21.2+)
*
* Key findings from real transaction analysis:
* 1. Peg-out transactions: Fee based only on vsize (MWEB weight doesn't add fee)
* 2. Peg-in transactions: Fee = (vsize * regular_rate) + (mweb_weight * mweb_rate)
* 3. Pure MWEB transactions: Fee = mweb_weight * mweb_rate only
* 4. MWEB fee rate is typically 100 satoshis per weight unit
*/
DEBUG - Server listening on 127.0.0.1:4224
DEBUG - Running accept thread
INFO - NetworkInfo { version: 210202, subversion: "/LitecoinCore:0.21.2.2/", relayfee: 1e-5 }
INFO - BlockchainInfo { chain: "main", blocks: 2912010, headers: 2912010, bestblockhash: "185133f403be40de68e6668ef5f6094614fb9461e7858e37657923233d848043", pruned: false, verificationprogress: 0.99999976, initialblockdownload: Some(false) }
DEBUG - opening DB at "/mempool/electrs-ltc/db/mainnet/newindex/txstore"
DEBUG - 2912046 blocks were added
DEBUG - opening DB at "/mempool/electrs-ltc/db/mainnet/newindex/history"
DEBUG - 2912046 blocks were indexed
DEBUG - opening DB at "/mempool/electrs-ltc/db/mainnet/newindex/cache"
{
"onboarding": {
"forgot_pin": "Ke harruar kodin PIN?",
"forgot_pin_description": "Ke harruar kodin PIN?\nShkruj seed phrase-in (24 fjalët) për të rivendosur kodin PIN.",
"enter_pin": "Vendos kodin PIN",
"reenter_pin": "Vendos kodin PIN",
"attempts_left_one": "{{count}} tentativë e mbetur.",
"attempts_left_other": "{{count}} tentativa të mbetura.",
"for_litecoin": "PËR LITECOIN",
"create_wallet": "Krijo Portofolin",
import React, {useEffect, useRef, useState} from 'react';
import {View, StyleSheet, TouchableOpacity, Image} from 'react-native';
import WebView from 'react-native-webview';
import DeviceInfo from 'react-native-device-info';
import {TransitionPresets} from '@react-navigation/stack';
import {RouteProp, useNavigation} from '@react-navigation/native';
import Header from '../components/Header';
import HeaderButton from '../components/Buttons/HeaderButton';
const selectUtxosForConversion = (
utxos: Utxo[],
amount: number,
): Accumulator => {
return utxos.reduce<Accumulator>(
({selectedUtxos, totalAmountSat}, utxo) => {
if (totalAmountSat >= amount) {
return {selectedUtxos, totalAmountSat};
}
return {
// Validation library from: https://github.com/ruigomeseu/bitcoin-address-validation
// Copyright (c) 2018 Rui Gomes hello@ruigomes.me
import {base58_to_binary} from 'base58-js';
import {bech32} from 'bech32';
import {createHash} from 'sha256-uint8array';
const sha256 = (payload: Uint8Array) => createHash().update(payload).digest();
enum Network {
mainnet = 'mainnet',
{
"onboarding": {
"forgot_pin": "Mot de passe oublié ?",
"forgot_pin_description": "Forgot your Pincode?\nEnter your seed phrase to reset your pincode.",
"enter_pin": "Entrez votre code PIN",
"attempts_left_one": "{{count}} attempt left.",
"attempts_left_other": "{{count}} attempts left.",
"for_litecoin": "FOR LITECOIN",
"create_wallet": "Create Wallet",
"already_wallet": "Already have a wallet? Log In",