litecore-lib-ltc 1.0.0 → 1.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -7
- package/src/api,js +24 -0
- package/src/index.js +52 -65
- package/src/wallet.js +45 -0
- package/src/network.js +0 -14
package/package.json
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litecore-lib-ltc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.4",
|
|
4
4
|
"main": "src/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
7
|
},
|
|
8
|
-
"keywords": [
|
|
8
|
+
"keywords": [
|
|
9
|
+
"litecoin",
|
|
10
|
+
"crypto",
|
|
11
|
+
"blockchain"
|
|
12
|
+
],
|
|
9
13
|
"license": "MIT",
|
|
10
14
|
"description": "Litecoin utility functions for transaction creation, signing, and broadcasting.",
|
|
15
|
+
"files": [
|
|
16
|
+
"src/"
|
|
17
|
+
],
|
|
11
18
|
"dependencies": {
|
|
12
19
|
"axios": "^1.13.6",
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
"tiny-secp256k1": "^2.2.4"
|
|
16
|
-
},
|
|
17
|
-
"files": ["src/"]
|
|
20
|
+
"bitcore-lib-ltc": "^10.10.5"
|
|
21
|
+
}
|
|
18
22
|
}
|
package/src/api,js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const BASE = 'https://api.blockcypher.com/v1/ltc/main';
|
|
3
|
+
|
|
4
|
+
async function getUTXOs(address) {
|
|
5
|
+
const res = await axios.get(`${BASE}/addrs/${address}?unspentOnly=true`);
|
|
6
|
+
return (res.data.txrefs || []).map(u => ({
|
|
7
|
+
txId: u.tx_hash,
|
|
8
|
+
outputIndex: u.tx_output_n,
|
|
9
|
+
satoshis: u.value,
|
|
10
|
+
script: res.data.txrefs ? null : u.script, // fetched separately if needed
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function broadcastTx(txHex) {
|
|
15
|
+
const res = await axios.post(`${BASE}/txs/push`, { tx: txHex });
|
|
16
|
+
return res.data.tx.hash;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function getFeeRate() {
|
|
20
|
+
const res = await axios.get(`${BASE}`);
|
|
21
|
+
return res.data.medium_fee_per_kb || 10000;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = { getUTXOs, broadcastTx, getFeeRate };
|
package/src/index.js
CHANGED
|
@@ -1,76 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Build and broadcast a Litecoin transaction
|
|
12
|
-
* @param {string} wif - Sender's WIF private key
|
|
13
|
-
* @param {string} toAddress - Recipient's LTC address
|
|
14
|
-
* @param {number} amountSatoshis - Amount in litoshis (1 LTC = 1e8)
|
|
15
|
-
* @param {number} feeSatoshis - Fee in litoshis
|
|
16
|
-
*/
|
|
17
|
-
async function sendLitecoin(wif, toAddress, amountSatoshis, feeSatoshis = 10000) {
|
|
18
|
-
const keyPair = ECPair.fromWIF(wif, LITECOIN);
|
|
19
|
-
const { address: fromAddress } = bitcoin.payments.p2pkh({
|
|
20
|
-
pubkey: keyPair.publicKey,
|
|
21
|
-
network: LITECOIN,
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// 1. Fetch UTXOs (using Blockcypher as example)
|
|
25
|
-
const utxoRes = await axios.get(
|
|
26
|
-
`https://api.blockcypher.com/v1/ltc/main/addrs/${fromAddress}?unspentOnly=true`
|
|
27
|
-
);
|
|
28
|
-
const utxos = utxoRes.data.txrefs || [];
|
|
29
|
-
|
|
30
|
-
if (!utxos.length) throw new Error('No UTXOs available');
|
|
31
|
-
|
|
32
|
-
// 2. Build transaction
|
|
33
|
-
const psbt = new bitcoin.Psbt({ network: LITECOIN });
|
|
34
|
-
let inputTotal = 0;
|
|
35
|
-
|
|
36
|
-
for (const utxo of utxos) {
|
|
37
|
-
// Fetch raw tx hex for each input
|
|
38
|
-
const txRes = await axios.get(
|
|
39
|
-
`https://api.blockcypher.com/v1/ltc/main/txs/${utxo.tx_hash}?includeHex=true`
|
|
40
|
-
);
|
|
41
|
-
psbt.addInput({
|
|
42
|
-
hash: utxo.tx_hash,
|
|
43
|
-
index: utxo.tx_output_n,
|
|
44
|
-
nonWitnessUtxo: Buffer.from(txRes.data.hex, 'hex'),
|
|
45
|
-
});
|
|
46
|
-
inputTotal += utxo.value;
|
|
47
|
-
if (inputTotal >= amountSatoshis + feeSatoshis) break;
|
|
1
|
+
const bitcore = require('bitcore-lib-ltc');
|
|
2
|
+
const { fromWIF, generateWallet, isValidAddress, getBalance } = require('./wallet');
|
|
3
|
+
const { getUTXOs, broadcastTx, getFeeRate } = require('./api');
|
|
4
|
+
|
|
5
|
+
class LitecoinWallet {
|
|
6
|
+
constructor(wif) {
|
|
7
|
+
const { privateKey, address } = fromWIF(wif);
|
|
8
|
+
this.privateKey = privateKey;
|
|
9
|
+
this.address = address;
|
|
48
10
|
}
|
|
49
11
|
|
|
50
|
-
|
|
51
|
-
|
|
12
|
+
static generate() {
|
|
13
|
+
return generateWallet();
|
|
52
14
|
}
|
|
53
15
|
|
|
54
|
-
|
|
55
|
-
|
|
16
|
+
static isValidAddress(address) {
|
|
17
|
+
return isValidAddress(address);
|
|
18
|
+
}
|
|
56
19
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
20
|
+
async getBalance() {
|
|
21
|
+
const utxos = await getUTXOs(this.address);
|
|
22
|
+
return utxos.reduce((sum, u) => sum + u.satoshis, 0);
|
|
60
23
|
}
|
|
61
24
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const rawTx = psbt.extractTransaction().toHex();
|
|
25
|
+
async getValue(address) {
|
|
26
|
+
return getBalance(address || this.address);
|
|
27
|
+
}
|
|
66
28
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
29
|
+
async send(toAddress, amountSatoshis, feeSatoshis) {
|
|
30
|
+
console.log(this.privateKey.toString());
|
|
31
|
+
if (!isValidAddress(toAddress)) {
|
|
32
|
+
throw new Error(`Invalid Litecoin address: ${toAddress}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const utxos = await getUTXOs(this.address);
|
|
36
|
+
const total = utxos.reduce((sum, u) => sum + u.satoshis, 0);
|
|
37
|
+
const fee = feeSatoshis || (await getFeeRate());
|
|
38
|
+
|
|
39
|
+
if (total < amountSatoshis + fee) {
|
|
40
|
+
throw new Error(`Insufficient funds. Have: ${total}, need: ${amountSatoshis + fee}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const tx = new bitcore.Transaction()
|
|
44
|
+
.from(utxos)
|
|
45
|
+
.to(toAddress, amountSatoshis)
|
|
46
|
+
.change(this.address)
|
|
47
|
+
.fee(fee)
|
|
48
|
+
.sign(this.privateKey);
|
|
49
|
+
|
|
50
|
+
const txHex = tx.serialize();
|
|
51
|
+
const txHash = await broadcastTx(txHex);
|
|
52
|
+
return txHash;
|
|
53
|
+
}
|
|
72
54
|
|
|
73
|
-
|
|
55
|
+
async sendMax(toAddress, feeSatoshis) {
|
|
56
|
+
const utxos = await getUTXOs(this.address);
|
|
57
|
+
const total = utxos.reduce((sum, u) => sum + u.satoshis, 0);
|
|
58
|
+
const fee = feeSatoshis || (await getFeeRate());
|
|
59
|
+
return this.send(toAddress, total - fee, fee);
|
|
60
|
+
}
|
|
74
61
|
}
|
|
75
62
|
|
|
76
|
-
module.exports = {
|
|
63
|
+
module.exports = { LitecoinWallet };
|
package/src/wallet.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const bitcore = require('bitcore-lib-ltc');
|
|
2
|
+
|
|
3
|
+
function fromWIF(wif) {
|
|
4
|
+
const privateKey = new bitcore.PrivateKey(wif);
|
|
5
|
+
const address = privateKey.toAddress().toString();
|
|
6
|
+
return { privateKey, address };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function generateWallet() {
|
|
10
|
+
const privateKey = new bitcore.PrivateKey();
|
|
11
|
+
return {
|
|
12
|
+
wif: privateKey.toWIF(),
|
|
13
|
+
address: privateKey.toAddress().toString(),
|
|
14
|
+
privateKey,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isValidAddress(address) {
|
|
19
|
+
return bitcore.Address.isValid(address);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function getBalance(address) {
|
|
23
|
+
const axios = require('axios');
|
|
24
|
+
|
|
25
|
+
const utxoRes = await axios.get(
|
|
26
|
+
`https://api.blockcypher.com/v1/ltc/main/addrs/${address}?unspentOnly=true`
|
|
27
|
+
);
|
|
28
|
+
const litoshis = utxoRes.data.final_balance || 0;
|
|
29
|
+
const ltc = litoshis / 1e8;
|
|
30
|
+
|
|
31
|
+
const priceRes = await axios.get(
|
|
32
|
+
'https://api.coingecko.com/api/v3/simple/price?ids=litecoin&vs_currencies=usd'
|
|
33
|
+
);
|
|
34
|
+
const usdPrice = priceRes.data.litecoin.usd;
|
|
35
|
+
const usd = parseFloat((ltc * usdPrice).toFixed(2));
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
litoshis,
|
|
39
|
+
ltc,
|
|
40
|
+
usd,
|
|
41
|
+
usdPrice,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { fromWIF, generateWallet, isValidAddress, getBalance };
|
package/src/network.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// src/network.js
|
|
2
|
-
const LITECOIN = {
|
|
3
|
-
messagePrefix: '\x19Litecoin Signed Message:\n',
|
|
4
|
-
bech32: 'ltc',
|
|
5
|
-
bip32: {
|
|
6
|
-
public: 0x019da462,
|
|
7
|
-
private: 0x019d9cfe,
|
|
8
|
-
},
|
|
9
|
-
pubKeyHash: 0x30, // L addresses
|
|
10
|
-
scriptHash: 0x32, // M addresses
|
|
11
|
-
wif: 0xb0,
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
module.exports = LITECOIN;
|