tetsuo-blockchain-wallet 1.1.5 → 1.2.2
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/DEPLOYMENT_INSTRUCTIONS.md +161 -0
- package/KEY_DERIVATION_FIX.md +91 -0
- package/dist/cli.js +21 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/rpc.d.ts +4 -0
- package/dist/rpc.js +32 -2
- package/dist/transaction.d.ts +3 -3
- package/dist/transaction.js +275 -24
- package/dist/wallet.d.ts +7 -2
- package/dist/wallet.js +23 -8
- package/package.json +9 -7
- package/src/cli.ts +20 -5
- package/src/index.ts +1 -0
- package/src/rpc.ts +36 -2
- package/src/transaction.ts +310 -22
- package/src/wallet.ts +25 -8
- package/test-send.js +151 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# TETSUO Wallet SDK - Deployment & Testing Guide
|
|
2
|
+
|
|
3
|
+
## Current Status
|
|
4
|
+
|
|
5
|
+
✅ **SDK Updates Completed:**
|
|
6
|
+
- Fixed transaction structure (missing script length field)
|
|
7
|
+
- Fixed DER signature encoding
|
|
8
|
+
- Added canonical S value normalization
|
|
9
|
+
- Implemented `/send` CLI command
|
|
10
|
+
|
|
11
|
+
⏳ **Server Updates Pending:**
|
|
12
|
+
- Added `hexToWif()` function for private key conversion
|
|
13
|
+
- Updated `/api/wallet/sign-and-broadcast` endpoint
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Step 1: Deploy Updated Server
|
|
18
|
+
|
|
19
|
+
### Option A: Using SSH (recommended)
|
|
20
|
+
|
|
21
|
+
Replace the server.js on the remote server:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
scp /Users/pchmirenko/Desktop/tetsuo-explorer-live/server.js root@165.227.69.246:/root/tetsuo-explorer/server.js
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then restart the service:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ssh root@165.227.69.246 "cd /root/tetsuo-explorer && pm2 restart tetsuo-explorer"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Option B: Manual Update
|
|
34
|
+
|
|
35
|
+
1. Open the file on the remote server:
|
|
36
|
+
```
|
|
37
|
+
/root/tetsuo-explorer/server.js
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
2. Find the `sign-and-broadcast` endpoint (around line 729)
|
|
41
|
+
|
|
42
|
+
3. Replace the endpoint with the updated version that includes `hexToWif()` function
|
|
43
|
+
|
|
44
|
+
4. Restart the service:
|
|
45
|
+
```bash
|
|
46
|
+
pm2 restart tetsuo-explorer
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Step 2: Test Locally
|
|
52
|
+
|
|
53
|
+
### Run the CLI
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd /private/tmp/tetsuo-wallet-sdk
|
|
57
|
+
node dist/cli.js
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Test the `/send` Command
|
|
61
|
+
|
|
62
|
+
In the CLI, run:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
/send
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Then follow the prompts:
|
|
69
|
+
- Recipient: `TVt1p2fcKTQXZVidshJbDCdYN3wxRnWLES` (or another address)
|
|
70
|
+
- Amount: `0.5` (TETSUO)
|
|
71
|
+
- Confirm: `yes`
|
|
72
|
+
|
|
73
|
+
### Expected Result
|
|
74
|
+
|
|
75
|
+
If server is updated:
|
|
76
|
+
```
|
|
77
|
+
✅ Transaction sent successfully!
|
|
78
|
+
TXID: a1b2c3d4e5f6...
|
|
79
|
+
Check at: https://tetsuoarena.com/tx/a1b2c3d4e5f6...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If server not updated:
|
|
83
|
+
```
|
|
84
|
+
✗ Error: Client signing verification failed, using server signature...
|
|
85
|
+
✗ Error: Invalid private key
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Step 3: What Each Fix Does
|
|
91
|
+
|
|
92
|
+
### Fix #1: Transaction Structure
|
|
93
|
+
- **File:** `src/transaction.ts` line 236
|
|
94
|
+
- **Issue:** Missing varint length field for input script
|
|
95
|
+
- **Effect:** Transactions no longer get "TX decode failed" error
|
|
96
|
+
- **Status:** ✅ DEPLOYED in SDK 1.2.1
|
|
97
|
+
|
|
98
|
+
### Fix #2: DER Signature Encoding
|
|
99
|
+
- **File:** `src/transaction.ts` line 372
|
|
100
|
+
- **Issue:** Incorrect length calculation (66 instead of 68 bytes)
|
|
101
|
+
- **Effect:** Signatures no longer get "Non-canonical DER" error
|
|
102
|
+
- **Status:** ✅ DEPLOYED in SDK 1.2.1
|
|
103
|
+
|
|
104
|
+
### Fix #3: WIF Key Conversion
|
|
105
|
+
- **File:** `server.js` line 730
|
|
106
|
+
- **Issue:** Server expects WIF format, not raw hex
|
|
107
|
+
- **Effect:** Server-side signing fallback will work
|
|
108
|
+
- **Status:** ⏳ PENDING - Needs server deployment
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Troubleshooting
|
|
113
|
+
|
|
114
|
+
### If you get "Invalid private key" error:
|
|
115
|
+
1. ❌ Server still has old code
|
|
116
|
+
2. ✅ Solution: Deploy updated server.js
|
|
117
|
+
|
|
118
|
+
### If you get "Signature must be zero for failed CHECK(MULTI)SIG":
|
|
119
|
+
1. This means DER encoding is fixed ✅
|
|
120
|
+
2. But ECDSA signature verification is still failing
|
|
121
|
+
3. Next step: Debug signature preimage creation
|
|
122
|
+
|
|
123
|
+
### If CLI won't start:
|
|
124
|
+
```bash
|
|
125
|
+
# Make sure you're in the right directory
|
|
126
|
+
cd /private/tmp/tetsuo-wallet-sdk
|
|
127
|
+
|
|
128
|
+
# Rebuild if needed
|
|
129
|
+
npm run build
|
|
130
|
+
|
|
131
|
+
# Run CLI
|
|
132
|
+
node dist/cli.js
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Files Modified
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
/private/tmp/tetsuo-wallet-sdk/
|
|
141
|
+
├── src/
|
|
142
|
+
│ ├── transaction.ts (FIXED - signature handling)
|
|
143
|
+
│ └── rpc.ts (comments updated)
|
|
144
|
+
├── package.json (version 1.2.1)
|
|
145
|
+
└── dist/ (built & ready)
|
|
146
|
+
|
|
147
|
+
/Users/pchmirenko/Desktop/tetsuo-explorer-live/
|
|
148
|
+
└── server.js (NEEDS DEPLOYMENT - WIF conversion added)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Next Steps
|
|
154
|
+
|
|
155
|
+
1. **Deploy server** (Step 1 above)
|
|
156
|
+
2. **Test locally** (Step 2 above)
|
|
157
|
+
3. **Report results**:
|
|
158
|
+
- What error do you get?
|
|
159
|
+
- Is the transaction being broadcast?
|
|
160
|
+
- Does the TXID appear?
|
|
161
|
+
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# TETSUO Wallet - Key Derivation Fix
|
|
2
|
+
|
|
3
|
+
## Problem Discovered
|
|
4
|
+
|
|
5
|
+
The wallet SDK was using **HMAC-based key derivation** instead of proper **secp256k1 elliptic curve point multiplication**. This is why client-side signatures are failing.
|
|
6
|
+
|
|
7
|
+
### What's Happening
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Private Key (same): f07313a484a766e1d62f4ad6345d54ef7544784edbad686742cb44df210c3ea6
|
|
11
|
+
|
|
12
|
+
SDK derives (HMAC): 026e9d770f8ba4132a4c7d0b9a14f466bf0b92607e9dfb7abcca3c445c350f9502
|
|
13
|
+
Correct (secp256k1): 024809982b467a559be83af9778784ba6a42a8593d5ead22e757e708db4a334f3d
|
|
14
|
+
|
|
15
|
+
These are DIFFERENT public keys!
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Why Signatures Fail
|
|
19
|
+
|
|
20
|
+
1. UTXO scriptPubKey expects signature valid for: `026e9d77...` (stored pubkey)
|
|
21
|
+
2. We sign with private key, but elliptic derives: `024809...` (correct pubkey)
|
|
22
|
+
3. Blockchain validates signature against wrong public key
|
|
23
|
+
4. Signature fails: `"Signature must be zero for failed CHECK(MULTI)SIG"`
|
|
24
|
+
|
|
25
|
+
## Solution
|
|
26
|
+
|
|
27
|
+
### Option 1: Create NEW Wallet with Correct Keys (RECOMMENDED)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# In CLI, delete old wallets and create new ones
|
|
31
|
+
/delete-wallet # Remove marcus, papa, popo
|
|
32
|
+
|
|
33
|
+
# Create new wallets - these will use correct secp256k1 derivation
|
|
34
|
+
/create-wallet # Create new wallet
|
|
35
|
+
/import-wallet # Or import from mnemonic
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then transfer your TETSUO from old address to new address via another method.
|
|
39
|
+
|
|
40
|
+
### Option 2: Use Server-Side Signing (Less Secure)
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Use /api/wallet/sign-and-broadcast endpoint
|
|
44
|
+
(Requires deploying updated server.js with hexToWif function)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Option 3: Keep Old Wallets, Accept HMAC Derivation
|
|
48
|
+
|
|
49
|
+
Accept the HMAC-based derivation as-is. This is not cryptographically correct but maintains compatibility with existing wallets/UTXOs.
|
|
50
|
+
|
|
51
|
+
Status: ✓ Currently implemented for backward compatibility
|
|
52
|
+
|
|
53
|
+
## What We Fixed
|
|
54
|
+
|
|
55
|
+
✅ **Transaction Structure** - Fixed missing varint length field for input scripts
|
|
56
|
+
✅ **DER Encoding** - Fixed signature length calculation
|
|
57
|
+
✅ **Canonical Signatures** - Added proper S value normalization
|
|
58
|
+
✅ **Documentation** - Clearly marked HMAC derivation as non-standard
|
|
59
|
+
|
|
60
|
+
## What Remains
|
|
61
|
+
|
|
62
|
+
The fundamental issue is that **all existing wallets** (marcus, papa, popo) were created with incorrect key derivation. To use proper secp256k1 signing:
|
|
63
|
+
|
|
64
|
+
1. Create new wallets
|
|
65
|
+
2. Transfer funds to new addresses
|
|
66
|
+
3. Use new wallets for all transactions
|
|
67
|
+
|
|
68
|
+
## Implementation Status
|
|
69
|
+
|
|
70
|
+
| Component | Status | Notes |
|
|
71
|
+
|-----------|--------|-------|
|
|
72
|
+
| Transaction Structure | ✅ FIXED | Input scripts properly sized |
|
|
73
|
+
| DER Encoding | ✅ FIXED | Signatures now canonical |
|
|
74
|
+
| Client Signing | ⏳ BLOCKED | Waiting for new wallets with correct keys |
|
|
75
|
+
| Server Signing | ⏳ PENDING | Needs server deployment + WIF conversion |
|
|
76
|
+
|
|
77
|
+
## Next Steps
|
|
78
|
+
|
|
79
|
+
1. **Understand the trade-off**:
|
|
80
|
+
- Keep old wallets = Can spend existing UTXOs but signature validation edge case
|
|
81
|
+
- Create new wallets = Proper crypto but need to transfer funds first
|
|
82
|
+
|
|
83
|
+
2. **Choose your approach**:
|
|
84
|
+
- Use server-side signing temporarily (less secure but works)
|
|
85
|
+
- Migrate to new wallets (more complex but fully secure)
|
|
86
|
+
|
|
87
|
+
3. **Test the chosen solution**
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
**Note**: The HMAC-based derivation is marked with a TODO for future migration to proper secp256k1. All new SDK versions should use correct elliptic curve math.
|
package/dist/cli.js
CHANGED
|
@@ -228,8 +228,12 @@ async function getBalance() {
|
|
|
228
228
|
console.log(chalk_1.default.yellow('⏳ Fetching balance...'));
|
|
229
229
|
const rpc = (0, index_1.createRPCClient)(RPC_URL);
|
|
230
230
|
const balance = await rpc.getBalance(wallet.address);
|
|
231
|
-
console.log(chalk_1.default.cyan('\n💰 Balance:'));
|
|
232
|
-
console.log(
|
|
231
|
+
console.log(chalk_1.default.cyan('\n💰 Balance Information:'));
|
|
232
|
+
console.log('─'.repeat(50));
|
|
233
|
+
console.log(chalk_1.default.yellow(' Wallet: ') + chalk_1.default.white(wallet.name));
|
|
234
|
+
console.log(chalk_1.default.yellow(' Address: ') + chalk_1.default.white(wallet.address));
|
|
235
|
+
console.log(chalk_1.default.yellow(' Balance: ') + chalk_1.default.green(`${balance.toFixed(8)} TETSUO`));
|
|
236
|
+
console.log('─'.repeat(50));
|
|
233
237
|
}
|
|
234
238
|
catch (error) {
|
|
235
239
|
console.log(chalk_1.default.red(`✗ Error: ${error.message}`));
|
|
@@ -247,10 +251,13 @@ async function getTransactions() {
|
|
|
247
251
|
const rpc = (0, index_1.createRPCClient)(RPC_URL);
|
|
248
252
|
const transactions = await rpc.getTransactionHistory(wallet.address);
|
|
249
253
|
if (transactions.length === 0) {
|
|
254
|
+
console.log(chalk_1.default.cyan('\n📋 Transaction History:'));
|
|
255
|
+
console.log(chalk_1.default.yellow(' Wallet: ') + wallet.name);
|
|
250
256
|
console.log(chalk_1.default.yellow('No transactions found'));
|
|
251
257
|
return;
|
|
252
258
|
}
|
|
253
259
|
console.log(chalk_1.default.cyan('\n📋 Transaction History:'));
|
|
260
|
+
console.log(chalk_1.default.yellow(' Wallet: ') + wallet.name);
|
|
254
261
|
console.log('─'.repeat(80));
|
|
255
262
|
transactions.forEach((tx) => {
|
|
256
263
|
const type = tx.isIncoming ? chalk_1.default.green('↓ RECEIVE') : chalk_1.default.yellow('↑ SEND');
|
|
@@ -323,10 +330,19 @@ async function sendTokens(rl) {
|
|
|
323
330
|
// Create and sign transaction
|
|
324
331
|
console.log(chalk_1.default.yellow('\n⏳ Signing transaction...'));
|
|
325
332
|
const txHex = (0, index_1.createTransactionHex)(txData.inputs, txData.outputs);
|
|
326
|
-
const signedTxHex = (0, index_1.signTransaction)(txHex, wallet.privateKey, txData.inputs);
|
|
327
|
-
// Broadcast
|
|
333
|
+
const signedTxHex = (0, index_1.signTransaction)(txHex, wallet.privateKey, txData.inputs, utxos);
|
|
334
|
+
// Broadcast or use server fallback
|
|
328
335
|
console.log(chalk_1.default.yellow(' Broadcasting...'));
|
|
329
|
-
|
|
336
|
+
let txid;
|
|
337
|
+
try {
|
|
338
|
+
// Try broadcasting signed transaction
|
|
339
|
+
txid = await rpc.broadcastTransaction(signedTxHex);
|
|
340
|
+
}
|
|
341
|
+
catch (broadcastError) {
|
|
342
|
+
console.log(chalk_1.default.yellow(' Client signing verification failed, using server signature...'));
|
|
343
|
+
// Fallback: Use server to sign and broadcast
|
|
344
|
+
txid = await rpc.signAndBroadcast(txHex, wallet.privateKey);
|
|
345
|
+
}
|
|
330
346
|
console.log(chalk_1.default.green('\n✅ Transaction sent successfully!'));
|
|
331
347
|
console.log(chalk_1.default.cyan('\n📊 Transaction Info:'));
|
|
332
348
|
console.log('─'.repeat(60));
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export { WalletConfig, GeneratedWallet, ImportedWallet, UTXO, TransactionInput, TransactionOutput, SignedTransaction, TransactionResult, Balance, Transaction, BlockchainInfo, WalletError, InvalidAddressError, InsufficientFundsError, RPCError } from './types';
|
|
5
5
|
export { sha256, doubleSha256, ripemd160, hash160, randomBytes, toHex, fromHex, toBase58, fromBase58, base58check, base58checkDecode } from './crypto';
|
|
6
6
|
export { generateAddress, isValidAddress, validateAddress, addressToHash160, getAddressHash } from './address';
|
|
7
|
-
export { generateWallet, importFromMnemonic, importFromPrivateKey, derivePublicKey, isValidMnemonic, getSupportedMnemonicLengths } from './wallet';
|
|
7
|
+
export { generateWallet, importFromMnemonic, importFromPrivateKey, derivePublicKey, derivePublicKeyLegacy, isValidMnemonic, getSupportedMnemonicLengths } from './wallet';
|
|
8
8
|
export { buildTransaction, createTransactionHex, signTransaction, estimateTransactionSize, estimateFee } from './transaction';
|
|
9
9
|
export { TetsuoRPC, createRPCClient } from './rpc';
|
|
10
10
|
export declare const VERSION = "1.0.0";
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* TETSUO Wallet SDK - Main Entry Point
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PACKAGE_INFO = exports.VERSION = exports.createRPCClient = exports.TetsuoRPC = exports.estimateFee = exports.estimateTransactionSize = exports.signTransaction = exports.createTransactionHex = exports.buildTransaction = exports.getSupportedMnemonicLengths = exports.isValidMnemonic = exports.derivePublicKey = exports.importFromPrivateKey = exports.importFromMnemonic = exports.generateWallet = exports.getAddressHash = exports.addressToHash160 = exports.validateAddress = exports.isValidAddress = exports.generateAddress = exports.base58checkDecode = exports.base58check = exports.fromBase58 = exports.toBase58 = exports.fromHex = exports.toHex = exports.randomBytes = exports.hash160 = exports.ripemd160 = exports.doubleSha256 = exports.sha256 = exports.RPCError = exports.InsufficientFundsError = exports.InvalidAddressError = exports.WalletError = void 0;
|
|
6
|
+
exports.PACKAGE_INFO = exports.VERSION = exports.createRPCClient = exports.TetsuoRPC = exports.estimateFee = exports.estimateTransactionSize = exports.signTransaction = exports.createTransactionHex = exports.buildTransaction = exports.getSupportedMnemonicLengths = exports.isValidMnemonic = exports.derivePublicKeyLegacy = exports.derivePublicKey = exports.importFromPrivateKey = exports.importFromMnemonic = exports.generateWallet = exports.getAddressHash = exports.addressToHash160 = exports.validateAddress = exports.isValidAddress = exports.generateAddress = exports.base58checkDecode = exports.base58check = exports.fromBase58 = exports.toBase58 = exports.fromHex = exports.toHex = exports.randomBytes = exports.hash160 = exports.ripemd160 = exports.doubleSha256 = exports.sha256 = exports.RPCError = exports.InsufficientFundsError = exports.InvalidAddressError = exports.WalletError = void 0;
|
|
7
7
|
// Type exports
|
|
8
8
|
var types_1 = require("./types");
|
|
9
9
|
Object.defineProperty(exports, "WalletError", { enumerable: true, get: function () { return types_1.WalletError; } });
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "generateWallet", { enumerable: true, get: functi
|
|
|
36
36
|
Object.defineProperty(exports, "importFromMnemonic", { enumerable: true, get: function () { return wallet_1.importFromMnemonic; } });
|
|
37
37
|
Object.defineProperty(exports, "importFromPrivateKey", { enumerable: true, get: function () { return wallet_1.importFromPrivateKey; } });
|
|
38
38
|
Object.defineProperty(exports, "derivePublicKey", { enumerable: true, get: function () { return wallet_1.derivePublicKey; } });
|
|
39
|
+
Object.defineProperty(exports, "derivePublicKeyLegacy", { enumerable: true, get: function () { return wallet_1.derivePublicKeyLegacy; } });
|
|
39
40
|
Object.defineProperty(exports, "isValidMnemonic", { enumerable: true, get: function () { return wallet_1.isValidMnemonic; } });
|
|
40
41
|
Object.defineProperty(exports, "getSupportedMnemonicLengths", { enumerable: true, get: function () { return wallet_1.getSupportedMnemonicLengths; } });
|
|
41
42
|
// Transaction exports
|
package/dist/rpc.d.ts
CHANGED
|
@@ -34,6 +34,10 @@ export declare class TetsuoRPC {
|
|
|
34
34
|
* Broadcast a signed transaction
|
|
35
35
|
*/
|
|
36
36
|
broadcastTransaction(transactionHex: string): Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Sign and broadcast transaction (for fallback when client signing fails)
|
|
39
|
+
*/
|
|
40
|
+
signAndBroadcast(unsignedHex: string, privateKey: string): Promise<string>;
|
|
37
41
|
/**
|
|
38
42
|
* Estimate fee for transaction
|
|
39
43
|
*/
|
package/dist/rpc.js
CHANGED
|
@@ -72,7 +72,17 @@ class TetsuoRPC {
|
|
|
72
72
|
async getUTXOs(address) {
|
|
73
73
|
try {
|
|
74
74
|
const response = await this.client.get(`/api/wallet/utxos/${address}`);
|
|
75
|
-
|
|
75
|
+
// Map server response to UTXO type (server uses 'amount', SDK expects 'value')
|
|
76
|
+
if (Array.isArray(response.data.utxos)) {
|
|
77
|
+
return response.data.utxos.map((utxo) => ({
|
|
78
|
+
txid: utxo.txid,
|
|
79
|
+
vout: utxo.vout,
|
|
80
|
+
value: utxo.amount ? Math.floor(utxo.amount * 100000000) : 0, // Convert TETSUO to satoshis
|
|
81
|
+
confirmations: utxo.confirmations || 0,
|
|
82
|
+
scriptPubKey: utxo.scriptPubKey
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
return [];
|
|
76
86
|
}
|
|
77
87
|
catch (error) {
|
|
78
88
|
throw this.handleError(`Failed to get UTXOs for ${address}`, error);
|
|
@@ -119,7 +129,7 @@ class TetsuoRPC {
|
|
|
119
129
|
*/
|
|
120
130
|
async broadcastTransaction(transactionHex) {
|
|
121
131
|
try {
|
|
122
|
-
const response = await this.client.post('/api/
|
|
132
|
+
const response = await this.client.post('/api/wallet/broadcast', {
|
|
123
133
|
hex: transactionHex
|
|
124
134
|
});
|
|
125
135
|
if (!response.data.txid) {
|
|
@@ -131,6 +141,26 @@ class TetsuoRPC {
|
|
|
131
141
|
throw this.handleError('Failed to broadcast transaction', error);
|
|
132
142
|
}
|
|
133
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Sign and broadcast transaction (for fallback when client signing fails)
|
|
146
|
+
*/
|
|
147
|
+
async signAndBroadcast(unsignedHex, privateKey) {
|
|
148
|
+
try {
|
|
149
|
+
// The private key can be either hex or WIF format
|
|
150
|
+
// If it's hex (64 chars), send as-is - server will convert it
|
|
151
|
+
const response = await this.client.post('/api/wallet/sign-and-broadcast', {
|
|
152
|
+
unsignedHex,
|
|
153
|
+
privateKey
|
|
154
|
+
});
|
|
155
|
+
if (!response.data.txid) {
|
|
156
|
+
throw new Error('No transaction ID returned');
|
|
157
|
+
}
|
|
158
|
+
return response.data.txid;
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
throw this.handleError('Failed to sign and broadcast transaction', error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
134
164
|
/**
|
|
135
165
|
* Estimate fee for transaction
|
|
136
166
|
*/
|
package/dist/transaction.d.ts
CHANGED
|
@@ -13,11 +13,11 @@ export declare function buildTransaction(fromAddress: string, toAddress: string,
|
|
|
13
13
|
/**
|
|
14
14
|
* Create transaction hex from inputs and outputs
|
|
15
15
|
*/
|
|
16
|
-
export declare function createTransactionHex(inputs: TransactionInput[], outputs: TransactionOutput[]): string;
|
|
16
|
+
export declare function createTransactionHex(inputs: TransactionInput[], outputs: TransactionOutput[], scriptPubKeys?: string[]): string;
|
|
17
17
|
/**
|
|
18
|
-
* Sign a transaction
|
|
18
|
+
* Sign a transaction with proper TETSUO key derivation
|
|
19
19
|
*/
|
|
20
|
-
export declare function signTransaction(transactionHex: string, privateKey: string, inputs: TransactionInput[]): string;
|
|
20
|
+
export declare function signTransaction(transactionHex: string, privateKey: string, inputs: TransactionInput[], utxos?: any[]): string;
|
|
21
21
|
/**
|
|
22
22
|
* Calculate transaction size
|
|
23
23
|
*/
|