@cryptforge/blockchain-btc 0.1.0
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/README.md +42 -0
- package/dist/index.cjs +281 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +52 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +244 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @cryptforge/blockchain-btc
|
|
2
|
+
|
|
3
|
+
Bitcoin blockchain adapter for the CryptForge SDK.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @cryptforge/blockchain-btc
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { BitcoinAdapter } from '@cryptforge/blockchain-btc';
|
|
15
|
+
import { setupCryptForgeHandlers } from '@cryptforge/transport-electron/main';
|
|
16
|
+
|
|
17
|
+
// In your Electron main process or Node.js server
|
|
18
|
+
setupCryptForgeHandlers({
|
|
19
|
+
blockchainAdapters: {
|
|
20
|
+
'Bitcoin': new BitcoinAdapter(),
|
|
21
|
+
},
|
|
22
|
+
// ... other options
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- Derives Bitcoin keys from BIP39 mnemonics
|
|
29
|
+
- Uses BIP44 derivation path: `m/44'/0'/0'/0/0`
|
|
30
|
+
- Generates P2PKH (Pay-to-Public-Key-Hash) addresses
|
|
31
|
+
- Provides chain metadata (name, symbol, CMC ID)
|
|
32
|
+
|
|
33
|
+
## Dependencies
|
|
34
|
+
|
|
35
|
+
This package includes all necessary Bitcoin-specific dependencies:
|
|
36
|
+
- `bitcoinjs-lib` - Bitcoin protocol implementation
|
|
37
|
+
- `bip32` - HD wallet key derivation
|
|
38
|
+
- `bip39` - Mnemonic generation and validation
|
|
39
|
+
- `tiny-secp256k1` - Elliptic curve cryptography
|
|
40
|
+
|
|
41
|
+
These dependencies are only added to your project if you install this package.
|
|
42
|
+
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
BitcoinAdapter: () => BitcoinAdapter
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
37
|
+
// src/BitcoinAdapter.ts
|
|
38
|
+
var import_bip39 = require("@scure/bip39");
|
|
39
|
+
var import_english = require("@scure/bip39/wordlists/english.js");
|
|
40
|
+
var import_bip32 = require("@scure/bip32");
|
|
41
|
+
var btc = __toESM(require("@scure/btc-signer"), 1);
|
|
42
|
+
var secp = __toESM(require("@noble/secp256k1"), 1);
|
|
43
|
+
var import_sha256 = require("@noble/hashes/sha256");
|
|
44
|
+
var BitcoinAdapter = class {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.chainData = {
|
|
47
|
+
name: "Bitcoin",
|
|
48
|
+
symbol: "BTC",
|
|
49
|
+
cmc_id: 1,
|
|
50
|
+
chainId: 0,
|
|
51
|
+
decimals: 8
|
|
52
|
+
};
|
|
53
|
+
this.coinType = 0;
|
|
54
|
+
// BIP44 coin type for Bitcoin
|
|
55
|
+
this.account = 0;
|
|
56
|
+
this.change = 0;
|
|
57
|
+
this.addressIndex = 0;
|
|
58
|
+
}
|
|
59
|
+
async deriveKeys(mnemonic) {
|
|
60
|
+
if (!(0, import_bip39.validateMnemonic)(mnemonic, import_english.wordlist)) {
|
|
61
|
+
throw new Error("Invalid mnemonic phrase");
|
|
62
|
+
}
|
|
63
|
+
const seed = (0, import_bip39.mnemonicToSeedSync)(mnemonic);
|
|
64
|
+
const hdKey = import_bip32.HDKey.fromMasterSeed(seed);
|
|
65
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${this.addressIndex}`;
|
|
66
|
+
const derived = hdKey.derive(path);
|
|
67
|
+
if (!derived.privateKey) {
|
|
68
|
+
throw new Error("Failed to derive private key from mnemonic");
|
|
69
|
+
}
|
|
70
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
71
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
72
|
+
const data = {
|
|
73
|
+
mnemonic,
|
|
74
|
+
seed,
|
|
75
|
+
privateKey: derived.privateKey,
|
|
76
|
+
privateKeyHex: this.bytesToHex(derived.privateKey),
|
|
77
|
+
publicKey,
|
|
78
|
+
publicKeyHex: this.bytesToHex(publicKey),
|
|
79
|
+
address,
|
|
80
|
+
path
|
|
81
|
+
};
|
|
82
|
+
return data;
|
|
83
|
+
}
|
|
84
|
+
async deriveKeysAtIndex(mnemonic, addressIndex) {
|
|
85
|
+
if (!(0, import_bip39.validateMnemonic)(mnemonic, import_english.wordlist)) {
|
|
86
|
+
throw new Error("Invalid mnemonic phrase");
|
|
87
|
+
}
|
|
88
|
+
const seed = (0, import_bip39.mnemonicToSeedSync)(mnemonic);
|
|
89
|
+
const hdKey = import_bip32.HDKey.fromMasterSeed(seed);
|
|
90
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${addressIndex}`;
|
|
91
|
+
const derived = hdKey.derive(path);
|
|
92
|
+
if (!derived.privateKey) {
|
|
93
|
+
throw new Error("Failed to derive private key from mnemonic");
|
|
94
|
+
}
|
|
95
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
96
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
97
|
+
const data = {
|
|
98
|
+
mnemonic,
|
|
99
|
+
seed,
|
|
100
|
+
privateKey: derived.privateKey,
|
|
101
|
+
privateKeyHex: this.bytesToHex(derived.privateKey),
|
|
102
|
+
publicKey,
|
|
103
|
+
publicKeyHex: this.bytesToHex(publicKey),
|
|
104
|
+
address,
|
|
105
|
+
path
|
|
106
|
+
};
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
async deriveKeysAtPath(mnemonic, path) {
|
|
110
|
+
if (!(0, import_bip39.validateMnemonic)(mnemonic, import_english.wordlist)) {
|
|
111
|
+
throw new Error("Invalid mnemonic phrase");
|
|
112
|
+
}
|
|
113
|
+
const seed = (0, import_bip39.mnemonicToSeedSync)(mnemonic);
|
|
114
|
+
const hdKey = import_bip32.HDKey.fromMasterSeed(seed);
|
|
115
|
+
const derived = hdKey.derive(path);
|
|
116
|
+
if (!derived.privateKey) {
|
|
117
|
+
throw new Error("Failed to derive private key from mnemonic");
|
|
118
|
+
}
|
|
119
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
120
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
121
|
+
const data = {
|
|
122
|
+
mnemonic,
|
|
123
|
+
seed,
|
|
124
|
+
privateKey: derived.privateKey,
|
|
125
|
+
privateKeyHex: this.bytesToHex(derived.privateKey),
|
|
126
|
+
publicKey,
|
|
127
|
+
publicKeyHex: this.bytesToHex(publicKey),
|
|
128
|
+
address,
|
|
129
|
+
path
|
|
130
|
+
};
|
|
131
|
+
return data;
|
|
132
|
+
}
|
|
133
|
+
async getAddressAtIndex(mnemonic, index) {
|
|
134
|
+
if (!(0, import_bip39.validateMnemonic)(mnemonic, import_english.wordlist)) {
|
|
135
|
+
throw new Error("Invalid mnemonic phrase");
|
|
136
|
+
}
|
|
137
|
+
const seed = (0, import_bip39.mnemonicToSeedSync)(mnemonic);
|
|
138
|
+
const hdKey = import_bip32.HDKey.fromMasterSeed(seed);
|
|
139
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;
|
|
140
|
+
const derived = hdKey.derive(path);
|
|
141
|
+
if (!derived.privateKey) {
|
|
142
|
+
throw new Error("Failed to derive key from mnemonic");
|
|
143
|
+
}
|
|
144
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
145
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
146
|
+
return {
|
|
147
|
+
address,
|
|
148
|
+
publicKey: this.bytesToHex(publicKey),
|
|
149
|
+
path
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
async getAddresses(mnemonic, startIndex, count) {
|
|
153
|
+
if (!(0, import_bip39.validateMnemonic)(mnemonic, import_english.wordlist)) {
|
|
154
|
+
throw new Error("Invalid mnemonic phrase");
|
|
155
|
+
}
|
|
156
|
+
const seed = (0, import_bip39.mnemonicToSeedSync)(mnemonic);
|
|
157
|
+
const hdKey = import_bip32.HDKey.fromMasterSeed(seed);
|
|
158
|
+
const addresses = [];
|
|
159
|
+
for (let i = 0; i < count; i++) {
|
|
160
|
+
const index = startIndex + i;
|
|
161
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;
|
|
162
|
+
const derived = hdKey.derive(path);
|
|
163
|
+
if (!derived.privateKey) {
|
|
164
|
+
throw new Error(`Failed to derive key at index ${index}`);
|
|
165
|
+
}
|
|
166
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
167
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
168
|
+
addresses.push({
|
|
169
|
+
address,
|
|
170
|
+
path,
|
|
171
|
+
index
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return addresses;
|
|
175
|
+
}
|
|
176
|
+
async signMessage(privateKey, message) {
|
|
177
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
178
|
+
const hash = (0, import_sha256.sha256)((0, import_sha256.sha256)(messageBytes));
|
|
179
|
+
const signature = await secp.signAsync(hash, privateKey);
|
|
180
|
+
return {
|
|
181
|
+
signature: this.bytesToHex(signature.toCompactRawBytes())
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
async signTransaction(privateKey, transaction) {
|
|
185
|
+
const tx = new btc.Transaction();
|
|
186
|
+
if (transaction.inputs && Array.isArray(transaction.inputs)) {
|
|
187
|
+
for (const input of transaction.inputs) {
|
|
188
|
+
tx.addInput({
|
|
189
|
+
txid: input.txid,
|
|
190
|
+
index: input.index,
|
|
191
|
+
...input
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (transaction.outputs && Array.isArray(transaction.outputs)) {
|
|
196
|
+
for (const output of transaction.outputs) {
|
|
197
|
+
tx.addOutputAddress(output.address, BigInt(output.amount));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
201
|
+
tx.signIdx(privateKey, i);
|
|
202
|
+
}
|
|
203
|
+
tx.finalize();
|
|
204
|
+
const signedTxHex = this.bytesToHex(tx.extract());
|
|
205
|
+
const txId = tx.id;
|
|
206
|
+
return {
|
|
207
|
+
signedTransaction: signedTxHex,
|
|
208
|
+
signature: txId
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
async verifySignature(message, signature, publicKey) {
|
|
212
|
+
try {
|
|
213
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
214
|
+
const hash = (0, import_sha256.sha256)((0, import_sha256.sha256)(messageBytes));
|
|
215
|
+
const signatureBytes = this.hexToBytes(signature);
|
|
216
|
+
const publicKeyBytes = this.hexToBytes(publicKey);
|
|
217
|
+
return secp.verify(signatureBytes, hash, publicKeyBytes);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Helper methods for byte/hex conversion
|
|
223
|
+
bytesToHex(bytes) {
|
|
224
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
225
|
+
}
|
|
226
|
+
hexToBytes(hex) {
|
|
227
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
228
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
229
|
+
bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
230
|
+
}
|
|
231
|
+
return bytes;
|
|
232
|
+
}
|
|
233
|
+
// Generate P2PKH (Pay-to-Public-Key-Hash) Bitcoin address
|
|
234
|
+
getP2PKHAddress(publicKey) {
|
|
235
|
+
const payment = btc.p2pkh(publicKey);
|
|
236
|
+
return payment.address || "";
|
|
237
|
+
}
|
|
238
|
+
// Blockchain data queries (not yet implemented for Bitcoin)
|
|
239
|
+
async getNativeBalance(address) {
|
|
240
|
+
throw new Error(
|
|
241
|
+
"getNativeBalance is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider."
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
async getTokenBalances(address) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
"getTokenBalances is not applicable for Bitcoin mainchain. For token support, consider using Bitcoin Layer-2 solutions."
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
async getTokenBalance(address, tokenAddress) {
|
|
250
|
+
throw new Error("getTokenBalance is not applicable for Bitcoin mainchain.");
|
|
251
|
+
}
|
|
252
|
+
async getTransactions(address, options) {
|
|
253
|
+
throw new Error(
|
|
254
|
+
"getTransactions is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider."
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
async getTokenTransfers(address, options) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
"getTokenTransfers is not applicable for Bitcoin mainchain."
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
// Transaction sending (not yet implemented)
|
|
263
|
+
async sendNativeToken(params) {
|
|
264
|
+
throw new Error(
|
|
265
|
+
"sendNativeToken is not yet implemented for Bitcoin. This requires UTXO selection, fee calculation, and proper transaction construction. Consider using a Bitcoin library like bitcoinjs-lib or a Bitcoin wallet SDK."
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
async sendToken(params) {
|
|
269
|
+
throw new Error("sendToken is not applicable for Bitcoin mainchain.");
|
|
270
|
+
}
|
|
271
|
+
async getTransactionStatus(hash) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
"getTransactionStatus is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider."
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
278
|
+
0 && (module.exports = {
|
|
279
|
+
BitcoinAdapter
|
|
280
|
+
});
|
|
281
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/BitcoinAdapter.ts"],"sourcesContent":["export { BitcoinAdapter } from \"./BitcoinAdapter\";\n\n","import { mnemonicToSeedSync, validateMnemonic } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\nimport { HDKey } from \"@scure/bip32\";\nimport * as btc from \"@scure/btc-signer\";\nimport * as secp from \"@noble/secp256k1\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport type { BlockchainAdapter, KeyData, ChainData } from \"@cryptforge/core\";\n\nexport class BitcoinAdapter implements BlockchainAdapter {\n readonly chainData: ChainData = {\n name: \"Bitcoin\",\n symbol: \"BTC\",\n cmc_id: 1,\n chainId: 0,\n decimals: 8,\n };\n\n private readonly coinType = 0; // BIP44 coin type for Bitcoin\n private readonly account = 0;\n private readonly change = 0;\n private readonly addressIndex = 0;\n\n async deriveKeys(mnemonic: string): Promise<KeyData> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${this.addressIndex}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive private key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n const data: KeyData = {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: derived.privateKey,\n privateKeyHex: this.bytesToHex(derived.privateKey),\n publicKey: publicKey,\n publicKeyHex: this.bytesToHex(publicKey),\n address: address,\n path: path,\n };\n\n return data;\n }\n\n async deriveKeysAtIndex(\n mnemonic: string,\n addressIndex: number\n ): Promise<KeyData> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${addressIndex}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive private key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n const data: KeyData = {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: derived.privateKey,\n privateKeyHex: this.bytesToHex(derived.privateKey),\n publicKey: publicKey,\n publicKeyHex: this.bytesToHex(publicKey),\n address: address,\n path: path,\n };\n\n return data;\n }\n\n async deriveKeysAtPath(mnemonic: string, path: string): Promise<KeyData> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive private key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n const data: KeyData = {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: derived.privateKey,\n privateKeyHex: this.bytesToHex(derived.privateKey),\n publicKey: publicKey,\n publicKeyHex: this.bytesToHex(publicKey),\n address: address,\n path: path,\n };\n\n return data;\n }\n\n async getAddressAtIndex(\n mnemonic: string,\n index: number\n ): Promise<{\n address: string;\n publicKey: string;\n path: string;\n }> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n return {\n address: address,\n publicKey: this.bytesToHex(publicKey),\n path: path,\n };\n }\n\n async getAddresses(\n mnemonic: string,\n startIndex: number,\n count: number\n ): Promise<Array<{ address: string; path: string; index: number }>> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const addresses: Array<{ address: string; path: string; index: number }> =\n [];\n\n for (let i = 0; i < count; i++) {\n const index = startIndex + i;\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(`Failed to derive key at index ${index}`);\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n addresses.push({\n address: address,\n path: path,\n index: index,\n });\n }\n\n return addresses;\n }\n\n async signMessage(\n privateKey: Uint8Array,\n message: string | Uint8Array\n ): Promise<{\n signature: string;\n }> {\n // Convert message to bytes\n const messageBytes =\n typeof message === \"string\" ? new TextEncoder().encode(message) : message;\n\n // Double SHA-256 hash (Bitcoin message signing)\n const hash = sha256(sha256(messageBytes));\n\n // Sign with secp256k1\n const signature = await secp.signAsync(hash, privateKey);\n\n return {\n signature: this.bytesToHex(signature.toCompactRawBytes()),\n };\n }\n\n async signTransaction(\n privateKey: Uint8Array,\n transaction: any\n ): Promise<{\n signedTransaction: any;\n signature: string;\n }> {\n // For Bitcoin, transaction signing is more complex and depends on the transaction type\n // This is a simplified implementation - in production, you'd need to handle:\n // - UTXO selection\n // - Multiple inputs/outputs\n // - Different address types (P2PKH, P2WPKH, P2SH, etc.)\n // - Fee calculation\n\n // Create a transaction using @scure/btc-signer\n const tx = new btc.Transaction();\n\n // Add inputs from transaction object\n if (transaction.inputs && Array.isArray(transaction.inputs)) {\n for (const input of transaction.inputs) {\n tx.addInput({\n txid: input.txid,\n index: input.index,\n ...input,\n });\n }\n }\n\n // Add outputs from transaction object\n if (transaction.outputs && Array.isArray(transaction.outputs)) {\n for (const output of transaction.outputs) {\n tx.addOutputAddress(output.address, BigInt(output.amount));\n }\n }\n\n // Sign all inputs with the private key\n // Note: This is a simplified approach. Real implementation would need\n // to handle different input types and signing methods\n for (let i = 0; i < tx.inputsLength; i++) {\n tx.signIdx(privateKey, i);\n }\n\n tx.finalize();\n\n const signedTxHex = this.bytesToHex(tx.extract());\n const txId = tx.id; // tx.id is already a hex string\n\n return {\n signedTransaction: signedTxHex,\n signature: txId,\n };\n }\n\n async verifySignature(\n message: string | Uint8Array,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n try {\n // Convert message to bytes\n const messageBytes =\n typeof message === \"string\"\n ? new TextEncoder().encode(message)\n : message;\n\n // Double SHA-256 hash (Bitcoin message signing)\n const hash = sha256(sha256(messageBytes));\n\n // Convert signature and public key from hex\n const signatureBytes = this.hexToBytes(signature);\n const publicKeyBytes = this.hexToBytes(publicKey);\n\n // Verify signature using secp256k1\n return secp.verify(signatureBytes, hash, publicKeyBytes);\n } catch (error) {\n return false;\n }\n }\n\n // Helper methods for byte/hex conversion\n private bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n private hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n }\n\n // Generate P2PKH (Pay-to-Public-Key-Hash) Bitcoin address\n private getP2PKHAddress(publicKey: Uint8Array): string {\n // Use @scure/btc-signer for proper address generation\n const payment = btc.p2pkh(publicKey);\n return payment.address || \"\";\n }\n\n // Blockchain data queries (not yet implemented for Bitcoin)\n async getNativeBalance(address: string): Promise<any> {\n throw new Error(\n \"getNativeBalance is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider.\"\n );\n }\n\n async getTokenBalances(address: string): Promise<any[]> {\n // Bitcoin doesn't have native token standards like ERC-20\n throw new Error(\n \"getTokenBalances is not applicable for Bitcoin mainchain. For token support, consider using Bitcoin Layer-2 solutions.\"\n );\n }\n\n async getTokenBalance(\n address: string,\n tokenAddress: string\n ): Promise<string> {\n throw new Error(\"getTokenBalance is not applicable for Bitcoin mainchain.\");\n }\n\n async getTransactions(address: string, options?: any): Promise<any[]> {\n throw new Error(\n \"getTransactions is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider.\"\n );\n }\n\n async getTokenTransfers(address: string, options?: any): Promise<any[]> {\n throw new Error(\n \"getTokenTransfers is not applicable for Bitcoin mainchain.\"\n );\n }\n\n // Transaction sending (not yet implemented)\n async sendNativeToken(params: {\n privateKey: Uint8Array;\n to: string;\n amount: string;\n }): Promise<any> {\n throw new Error(\n \"sendNativeToken is not yet implemented for Bitcoin. This requires UTXO selection, fee calculation, and proper transaction construction. \" +\n \"Consider using a Bitcoin library like bitcoinjs-lib or a Bitcoin wallet SDK.\"\n );\n }\n\n async sendToken(params: {\n privateKey: Uint8Array;\n to: string;\n tokenAddress: string;\n amount: string;\n }): Promise<any> {\n throw new Error(\"sendToken is not applicable for Bitcoin mainchain.\");\n }\n\n async getTransactionStatus(hash: string): Promise<any> {\n throw new Error(\n \"getTransactionStatus is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider.\"\n );\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BlockchainAdapter, ChainData, KeyData } from '@cryptforge/core';
|
|
2
|
+
|
|
3
|
+
declare class BitcoinAdapter implements BlockchainAdapter {
|
|
4
|
+
readonly chainData: ChainData;
|
|
5
|
+
private readonly coinType;
|
|
6
|
+
private readonly account;
|
|
7
|
+
private readonly change;
|
|
8
|
+
private readonly addressIndex;
|
|
9
|
+
deriveKeys(mnemonic: string): Promise<KeyData>;
|
|
10
|
+
deriveKeysAtIndex(mnemonic: string, addressIndex: number): Promise<KeyData>;
|
|
11
|
+
deriveKeysAtPath(mnemonic: string, path: string): Promise<KeyData>;
|
|
12
|
+
getAddressAtIndex(mnemonic: string, index: number): Promise<{
|
|
13
|
+
address: string;
|
|
14
|
+
publicKey: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}>;
|
|
17
|
+
getAddresses(mnemonic: string, startIndex: number, count: number): Promise<Array<{
|
|
18
|
+
address: string;
|
|
19
|
+
path: string;
|
|
20
|
+
index: number;
|
|
21
|
+
}>>;
|
|
22
|
+
signMessage(privateKey: Uint8Array, message: string | Uint8Array): Promise<{
|
|
23
|
+
signature: string;
|
|
24
|
+
}>;
|
|
25
|
+
signTransaction(privateKey: Uint8Array, transaction: any): Promise<{
|
|
26
|
+
signedTransaction: any;
|
|
27
|
+
signature: string;
|
|
28
|
+
}>;
|
|
29
|
+
verifySignature(message: string | Uint8Array, signature: string, publicKey: string): Promise<boolean>;
|
|
30
|
+
private bytesToHex;
|
|
31
|
+
private hexToBytes;
|
|
32
|
+
private getP2PKHAddress;
|
|
33
|
+
getNativeBalance(address: string): Promise<any>;
|
|
34
|
+
getTokenBalances(address: string): Promise<any[]>;
|
|
35
|
+
getTokenBalance(address: string, tokenAddress: string): Promise<string>;
|
|
36
|
+
getTransactions(address: string, options?: any): Promise<any[]>;
|
|
37
|
+
getTokenTransfers(address: string, options?: any): Promise<any[]>;
|
|
38
|
+
sendNativeToken(params: {
|
|
39
|
+
privateKey: Uint8Array;
|
|
40
|
+
to: string;
|
|
41
|
+
amount: string;
|
|
42
|
+
}): Promise<any>;
|
|
43
|
+
sendToken(params: {
|
|
44
|
+
privateKey: Uint8Array;
|
|
45
|
+
to: string;
|
|
46
|
+
tokenAddress: string;
|
|
47
|
+
amount: string;
|
|
48
|
+
}): Promise<any>;
|
|
49
|
+
getTransactionStatus(hash: string): Promise<any>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { BitcoinAdapter };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BlockchainAdapter, ChainData, KeyData } from '@cryptforge/core';
|
|
2
|
+
|
|
3
|
+
declare class BitcoinAdapter implements BlockchainAdapter {
|
|
4
|
+
readonly chainData: ChainData;
|
|
5
|
+
private readonly coinType;
|
|
6
|
+
private readonly account;
|
|
7
|
+
private readonly change;
|
|
8
|
+
private readonly addressIndex;
|
|
9
|
+
deriveKeys(mnemonic: string): Promise<KeyData>;
|
|
10
|
+
deriveKeysAtIndex(mnemonic: string, addressIndex: number): Promise<KeyData>;
|
|
11
|
+
deriveKeysAtPath(mnemonic: string, path: string): Promise<KeyData>;
|
|
12
|
+
getAddressAtIndex(mnemonic: string, index: number): Promise<{
|
|
13
|
+
address: string;
|
|
14
|
+
publicKey: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}>;
|
|
17
|
+
getAddresses(mnemonic: string, startIndex: number, count: number): Promise<Array<{
|
|
18
|
+
address: string;
|
|
19
|
+
path: string;
|
|
20
|
+
index: number;
|
|
21
|
+
}>>;
|
|
22
|
+
signMessage(privateKey: Uint8Array, message: string | Uint8Array): Promise<{
|
|
23
|
+
signature: string;
|
|
24
|
+
}>;
|
|
25
|
+
signTransaction(privateKey: Uint8Array, transaction: any): Promise<{
|
|
26
|
+
signedTransaction: any;
|
|
27
|
+
signature: string;
|
|
28
|
+
}>;
|
|
29
|
+
verifySignature(message: string | Uint8Array, signature: string, publicKey: string): Promise<boolean>;
|
|
30
|
+
private bytesToHex;
|
|
31
|
+
private hexToBytes;
|
|
32
|
+
private getP2PKHAddress;
|
|
33
|
+
getNativeBalance(address: string): Promise<any>;
|
|
34
|
+
getTokenBalances(address: string): Promise<any[]>;
|
|
35
|
+
getTokenBalance(address: string, tokenAddress: string): Promise<string>;
|
|
36
|
+
getTransactions(address: string, options?: any): Promise<any[]>;
|
|
37
|
+
getTokenTransfers(address: string, options?: any): Promise<any[]>;
|
|
38
|
+
sendNativeToken(params: {
|
|
39
|
+
privateKey: Uint8Array;
|
|
40
|
+
to: string;
|
|
41
|
+
amount: string;
|
|
42
|
+
}): Promise<any>;
|
|
43
|
+
sendToken(params: {
|
|
44
|
+
privateKey: Uint8Array;
|
|
45
|
+
to: string;
|
|
46
|
+
tokenAddress: string;
|
|
47
|
+
amount: string;
|
|
48
|
+
}): Promise<any>;
|
|
49
|
+
getTransactionStatus(hash: string): Promise<any>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { BitcoinAdapter };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// src/BitcoinAdapter.ts
|
|
2
|
+
import { mnemonicToSeedSync, validateMnemonic } from "@scure/bip39";
|
|
3
|
+
import { wordlist } from "@scure/bip39/wordlists/english.js";
|
|
4
|
+
import { HDKey } from "@scure/bip32";
|
|
5
|
+
import * as btc from "@scure/btc-signer";
|
|
6
|
+
import * as secp from "@noble/secp256k1";
|
|
7
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
8
|
+
var BitcoinAdapter = class {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.chainData = {
|
|
11
|
+
name: "Bitcoin",
|
|
12
|
+
symbol: "BTC",
|
|
13
|
+
cmc_id: 1,
|
|
14
|
+
chainId: 0,
|
|
15
|
+
decimals: 8
|
|
16
|
+
};
|
|
17
|
+
this.coinType = 0;
|
|
18
|
+
// BIP44 coin type for Bitcoin
|
|
19
|
+
this.account = 0;
|
|
20
|
+
this.change = 0;
|
|
21
|
+
this.addressIndex = 0;
|
|
22
|
+
}
|
|
23
|
+
async deriveKeys(mnemonic) {
|
|
24
|
+
if (!validateMnemonic(mnemonic, wordlist)) {
|
|
25
|
+
throw new Error("Invalid mnemonic phrase");
|
|
26
|
+
}
|
|
27
|
+
const seed = mnemonicToSeedSync(mnemonic);
|
|
28
|
+
const hdKey = HDKey.fromMasterSeed(seed);
|
|
29
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${this.addressIndex}`;
|
|
30
|
+
const derived = hdKey.derive(path);
|
|
31
|
+
if (!derived.privateKey) {
|
|
32
|
+
throw new Error("Failed to derive private key from mnemonic");
|
|
33
|
+
}
|
|
34
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
35
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
36
|
+
const data = {
|
|
37
|
+
mnemonic,
|
|
38
|
+
seed,
|
|
39
|
+
privateKey: derived.privateKey,
|
|
40
|
+
privateKeyHex: this.bytesToHex(derived.privateKey),
|
|
41
|
+
publicKey,
|
|
42
|
+
publicKeyHex: this.bytesToHex(publicKey),
|
|
43
|
+
address,
|
|
44
|
+
path
|
|
45
|
+
};
|
|
46
|
+
return data;
|
|
47
|
+
}
|
|
48
|
+
async deriveKeysAtIndex(mnemonic, addressIndex) {
|
|
49
|
+
if (!validateMnemonic(mnemonic, wordlist)) {
|
|
50
|
+
throw new Error("Invalid mnemonic phrase");
|
|
51
|
+
}
|
|
52
|
+
const seed = mnemonicToSeedSync(mnemonic);
|
|
53
|
+
const hdKey = HDKey.fromMasterSeed(seed);
|
|
54
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${addressIndex}`;
|
|
55
|
+
const derived = hdKey.derive(path);
|
|
56
|
+
if (!derived.privateKey) {
|
|
57
|
+
throw new Error("Failed to derive private key from mnemonic");
|
|
58
|
+
}
|
|
59
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
60
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
61
|
+
const data = {
|
|
62
|
+
mnemonic,
|
|
63
|
+
seed,
|
|
64
|
+
privateKey: derived.privateKey,
|
|
65
|
+
privateKeyHex: this.bytesToHex(derived.privateKey),
|
|
66
|
+
publicKey,
|
|
67
|
+
publicKeyHex: this.bytesToHex(publicKey),
|
|
68
|
+
address,
|
|
69
|
+
path
|
|
70
|
+
};
|
|
71
|
+
return data;
|
|
72
|
+
}
|
|
73
|
+
async deriveKeysAtPath(mnemonic, path) {
|
|
74
|
+
if (!validateMnemonic(mnemonic, wordlist)) {
|
|
75
|
+
throw new Error("Invalid mnemonic phrase");
|
|
76
|
+
}
|
|
77
|
+
const seed = mnemonicToSeedSync(mnemonic);
|
|
78
|
+
const hdKey = HDKey.fromMasterSeed(seed);
|
|
79
|
+
const derived = hdKey.derive(path);
|
|
80
|
+
if (!derived.privateKey) {
|
|
81
|
+
throw new Error("Failed to derive private key from mnemonic");
|
|
82
|
+
}
|
|
83
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
84
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
85
|
+
const data = {
|
|
86
|
+
mnemonic,
|
|
87
|
+
seed,
|
|
88
|
+
privateKey: derived.privateKey,
|
|
89
|
+
privateKeyHex: this.bytesToHex(derived.privateKey),
|
|
90
|
+
publicKey,
|
|
91
|
+
publicKeyHex: this.bytesToHex(publicKey),
|
|
92
|
+
address,
|
|
93
|
+
path
|
|
94
|
+
};
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
async getAddressAtIndex(mnemonic, index) {
|
|
98
|
+
if (!validateMnemonic(mnemonic, wordlist)) {
|
|
99
|
+
throw new Error("Invalid mnemonic phrase");
|
|
100
|
+
}
|
|
101
|
+
const seed = mnemonicToSeedSync(mnemonic);
|
|
102
|
+
const hdKey = HDKey.fromMasterSeed(seed);
|
|
103
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;
|
|
104
|
+
const derived = hdKey.derive(path);
|
|
105
|
+
if (!derived.privateKey) {
|
|
106
|
+
throw new Error("Failed to derive key from mnemonic");
|
|
107
|
+
}
|
|
108
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
109
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
110
|
+
return {
|
|
111
|
+
address,
|
|
112
|
+
publicKey: this.bytesToHex(publicKey),
|
|
113
|
+
path
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
async getAddresses(mnemonic, startIndex, count) {
|
|
117
|
+
if (!validateMnemonic(mnemonic, wordlist)) {
|
|
118
|
+
throw new Error("Invalid mnemonic phrase");
|
|
119
|
+
}
|
|
120
|
+
const seed = mnemonicToSeedSync(mnemonic);
|
|
121
|
+
const hdKey = HDKey.fromMasterSeed(seed);
|
|
122
|
+
const addresses = [];
|
|
123
|
+
for (let i = 0; i < count; i++) {
|
|
124
|
+
const index = startIndex + i;
|
|
125
|
+
const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;
|
|
126
|
+
const derived = hdKey.derive(path);
|
|
127
|
+
if (!derived.privateKey) {
|
|
128
|
+
throw new Error(`Failed to derive key at index ${index}`);
|
|
129
|
+
}
|
|
130
|
+
const publicKey = secp.getPublicKey(derived.privateKey, true);
|
|
131
|
+
const address = this.getP2PKHAddress(publicKey);
|
|
132
|
+
addresses.push({
|
|
133
|
+
address,
|
|
134
|
+
path,
|
|
135
|
+
index
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return addresses;
|
|
139
|
+
}
|
|
140
|
+
async signMessage(privateKey, message) {
|
|
141
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
142
|
+
const hash = sha256(sha256(messageBytes));
|
|
143
|
+
const signature = await secp.signAsync(hash, privateKey);
|
|
144
|
+
return {
|
|
145
|
+
signature: this.bytesToHex(signature.toCompactRawBytes())
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
async signTransaction(privateKey, transaction) {
|
|
149
|
+
const tx = new btc.Transaction();
|
|
150
|
+
if (transaction.inputs && Array.isArray(transaction.inputs)) {
|
|
151
|
+
for (const input of transaction.inputs) {
|
|
152
|
+
tx.addInput({
|
|
153
|
+
txid: input.txid,
|
|
154
|
+
index: input.index,
|
|
155
|
+
...input
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (transaction.outputs && Array.isArray(transaction.outputs)) {
|
|
160
|
+
for (const output of transaction.outputs) {
|
|
161
|
+
tx.addOutputAddress(output.address, BigInt(output.amount));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
165
|
+
tx.signIdx(privateKey, i);
|
|
166
|
+
}
|
|
167
|
+
tx.finalize();
|
|
168
|
+
const signedTxHex = this.bytesToHex(tx.extract());
|
|
169
|
+
const txId = tx.id;
|
|
170
|
+
return {
|
|
171
|
+
signedTransaction: signedTxHex,
|
|
172
|
+
signature: txId
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async verifySignature(message, signature, publicKey) {
|
|
176
|
+
try {
|
|
177
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
178
|
+
const hash = sha256(sha256(messageBytes));
|
|
179
|
+
const signatureBytes = this.hexToBytes(signature);
|
|
180
|
+
const publicKeyBytes = this.hexToBytes(publicKey);
|
|
181
|
+
return secp.verify(signatureBytes, hash, publicKeyBytes);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Helper methods for byte/hex conversion
|
|
187
|
+
bytesToHex(bytes) {
|
|
188
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
189
|
+
}
|
|
190
|
+
hexToBytes(hex) {
|
|
191
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
192
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
193
|
+
bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
194
|
+
}
|
|
195
|
+
return bytes;
|
|
196
|
+
}
|
|
197
|
+
// Generate P2PKH (Pay-to-Public-Key-Hash) Bitcoin address
|
|
198
|
+
getP2PKHAddress(publicKey) {
|
|
199
|
+
const payment = btc.p2pkh(publicKey);
|
|
200
|
+
return payment.address || "";
|
|
201
|
+
}
|
|
202
|
+
// Blockchain data queries (not yet implemented for Bitcoin)
|
|
203
|
+
async getNativeBalance(address) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
"getNativeBalance is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider."
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
async getTokenBalances(address) {
|
|
209
|
+
throw new Error(
|
|
210
|
+
"getTokenBalances is not applicable for Bitcoin mainchain. For token support, consider using Bitcoin Layer-2 solutions."
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
async getTokenBalance(address, tokenAddress) {
|
|
214
|
+
throw new Error("getTokenBalance is not applicable for Bitcoin mainchain.");
|
|
215
|
+
}
|
|
216
|
+
async getTransactions(address, options) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
"getTransactions is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider."
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
async getTokenTransfers(address, options) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
"getTokenTransfers is not applicable for Bitcoin mainchain."
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
// Transaction sending (not yet implemented)
|
|
227
|
+
async sendNativeToken(params) {
|
|
228
|
+
throw new Error(
|
|
229
|
+
"sendNativeToken is not yet implemented for Bitcoin. This requires UTXO selection, fee calculation, and proper transaction construction. Consider using a Bitcoin library like bitcoinjs-lib or a Bitcoin wallet SDK."
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
async sendToken(params) {
|
|
233
|
+
throw new Error("sendToken is not applicable for Bitcoin mainchain.");
|
|
234
|
+
}
|
|
235
|
+
async getTransactionStatus(hash) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
"getTransactionStatus is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider."
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
export {
|
|
242
|
+
BitcoinAdapter
|
|
243
|
+
};
|
|
244
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/BitcoinAdapter.ts"],"sourcesContent":["import { mnemonicToSeedSync, validateMnemonic } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\nimport { HDKey } from \"@scure/bip32\";\nimport * as btc from \"@scure/btc-signer\";\nimport * as secp from \"@noble/secp256k1\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport type { BlockchainAdapter, KeyData, ChainData } from \"@cryptforge/core\";\n\nexport class BitcoinAdapter implements BlockchainAdapter {\n readonly chainData: ChainData = {\n name: \"Bitcoin\",\n symbol: \"BTC\",\n cmc_id: 1,\n chainId: 0,\n decimals: 8,\n };\n\n private readonly coinType = 0; // BIP44 coin type for Bitcoin\n private readonly account = 0;\n private readonly change = 0;\n private readonly addressIndex = 0;\n\n async deriveKeys(mnemonic: string): Promise<KeyData> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${this.addressIndex}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive private key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n const data: KeyData = {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: derived.privateKey,\n privateKeyHex: this.bytesToHex(derived.privateKey),\n publicKey: publicKey,\n publicKeyHex: this.bytesToHex(publicKey),\n address: address,\n path: path,\n };\n\n return data;\n }\n\n async deriveKeysAtIndex(\n mnemonic: string,\n addressIndex: number\n ): Promise<KeyData> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${addressIndex}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive private key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n const data: KeyData = {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: derived.privateKey,\n privateKeyHex: this.bytesToHex(derived.privateKey),\n publicKey: publicKey,\n publicKeyHex: this.bytesToHex(publicKey),\n address: address,\n path: path,\n };\n\n return data;\n }\n\n async deriveKeysAtPath(mnemonic: string, path: string): Promise<KeyData> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive private key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n const data: KeyData = {\n mnemonic: mnemonic,\n seed: seed,\n privateKey: derived.privateKey,\n privateKeyHex: this.bytesToHex(derived.privateKey),\n publicKey: publicKey,\n publicKeyHex: this.bytesToHex(publicKey),\n address: address,\n path: path,\n };\n\n return data;\n }\n\n async getAddressAtIndex(\n mnemonic: string,\n index: number\n ): Promise<{\n address: string;\n publicKey: string;\n path: string;\n }> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(\"Failed to derive key from mnemonic\");\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n return {\n address: address,\n publicKey: this.bytesToHex(publicKey),\n path: path,\n };\n }\n\n async getAddresses(\n mnemonic: string,\n startIndex: number,\n count: number\n ): Promise<Array<{ address: string; path: string; index: number }>> {\n // Validate mnemonic\n if (!validateMnemonic(mnemonic, wordlist)) {\n throw new Error(\"Invalid mnemonic phrase\");\n }\n\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const addresses: Array<{ address: string; path: string; index: number }> =\n [];\n\n for (let i = 0; i < count; i++) {\n const index = startIndex + i;\n const path = `m/44'/${this.coinType}'/${this.account}'/${this.change}/${index}`;\n const derived = hdKey.derive(path);\n\n if (!derived.privateKey) {\n throw new Error(`Failed to derive key at index ${index}`);\n }\n\n const publicKey = secp.getPublicKey(derived.privateKey, true); // compressed\n const address = this.getP2PKHAddress(publicKey);\n\n addresses.push({\n address: address,\n path: path,\n index: index,\n });\n }\n\n return addresses;\n }\n\n async signMessage(\n privateKey: Uint8Array,\n message: string | Uint8Array\n ): Promise<{\n signature: string;\n }> {\n // Convert message to bytes\n const messageBytes =\n typeof message === \"string\" ? new TextEncoder().encode(message) : message;\n\n // Double SHA-256 hash (Bitcoin message signing)\n const hash = sha256(sha256(messageBytes));\n\n // Sign with secp256k1\n const signature = await secp.signAsync(hash, privateKey);\n\n return {\n signature: this.bytesToHex(signature.toCompactRawBytes()),\n };\n }\n\n async signTransaction(\n privateKey: Uint8Array,\n transaction: any\n ): Promise<{\n signedTransaction: any;\n signature: string;\n }> {\n // For Bitcoin, transaction signing is more complex and depends on the transaction type\n // This is a simplified implementation - in production, you'd need to handle:\n // - UTXO selection\n // - Multiple inputs/outputs\n // - Different address types (P2PKH, P2WPKH, P2SH, etc.)\n // - Fee calculation\n\n // Create a transaction using @scure/btc-signer\n const tx = new btc.Transaction();\n\n // Add inputs from transaction object\n if (transaction.inputs && Array.isArray(transaction.inputs)) {\n for (const input of transaction.inputs) {\n tx.addInput({\n txid: input.txid,\n index: input.index,\n ...input,\n });\n }\n }\n\n // Add outputs from transaction object\n if (transaction.outputs && Array.isArray(transaction.outputs)) {\n for (const output of transaction.outputs) {\n tx.addOutputAddress(output.address, BigInt(output.amount));\n }\n }\n\n // Sign all inputs with the private key\n // Note: This is a simplified approach. Real implementation would need\n // to handle different input types and signing methods\n for (let i = 0; i < tx.inputsLength; i++) {\n tx.signIdx(privateKey, i);\n }\n\n tx.finalize();\n\n const signedTxHex = this.bytesToHex(tx.extract());\n const txId = tx.id; // tx.id is already a hex string\n\n return {\n signedTransaction: signedTxHex,\n signature: txId,\n };\n }\n\n async verifySignature(\n message: string | Uint8Array,\n signature: string,\n publicKey: string\n ): Promise<boolean> {\n try {\n // Convert message to bytes\n const messageBytes =\n typeof message === \"string\"\n ? new TextEncoder().encode(message)\n : message;\n\n // Double SHA-256 hash (Bitcoin message signing)\n const hash = sha256(sha256(messageBytes));\n\n // Convert signature and public key from hex\n const signatureBytes = this.hexToBytes(signature);\n const publicKeyBytes = this.hexToBytes(publicKey);\n\n // Verify signature using secp256k1\n return secp.verify(signatureBytes, hash, publicKeyBytes);\n } catch (error) {\n return false;\n }\n }\n\n // Helper methods for byte/hex conversion\n private bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n private hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n }\n\n // Generate P2PKH (Pay-to-Public-Key-Hash) Bitcoin address\n private getP2PKHAddress(publicKey: Uint8Array): string {\n // Use @scure/btc-signer for proper address generation\n const payment = btc.p2pkh(publicKey);\n return payment.address || \"\";\n }\n\n // Blockchain data queries (not yet implemented for Bitcoin)\n async getNativeBalance(address: string): Promise<any> {\n throw new Error(\n \"getNativeBalance is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider.\"\n );\n }\n\n async getTokenBalances(address: string): Promise<any[]> {\n // Bitcoin doesn't have native token standards like ERC-20\n throw new Error(\n \"getTokenBalances is not applicable for Bitcoin mainchain. For token support, consider using Bitcoin Layer-2 solutions.\"\n );\n }\n\n async getTokenBalance(\n address: string,\n tokenAddress: string\n ): Promise<string> {\n throw new Error(\"getTokenBalance is not applicable for Bitcoin mainchain.\");\n }\n\n async getTransactions(address: string, options?: any): Promise<any[]> {\n throw new Error(\n \"getTransactions is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider.\"\n );\n }\n\n async getTokenTransfers(address: string, options?: any): Promise<any[]> {\n throw new Error(\n \"getTokenTransfers is not applicable for Bitcoin mainchain.\"\n );\n }\n\n // Transaction sending (not yet implemented)\n async sendNativeToken(params: {\n privateKey: Uint8Array;\n to: string;\n amount: string;\n }): Promise<any> {\n throw new Error(\n \"sendNativeToken is not yet implemented for Bitcoin. This requires UTXO selection, fee calculation, and proper transaction construction. \" +\n \"Consider using a Bitcoin library like bitcoinjs-lib or a Bitcoin wallet SDK.\"\n );\n }\n\n async sendToken(params: {\n privateKey: Uint8Array;\n to: string;\n tokenAddress: string;\n amount: string;\n }): Promise<any> {\n throw new Error(\"sendToken is not applicable for Bitcoin mainchain.\");\n }\n\n async getTransactionStatus(hash: string): Promise<any> {\n throw new Error(\n \"getTransactionStatus is not yet implemented for Bitcoin. Please use a block explorer API or Bitcoin RPC provider.\"\n );\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cryptforge/blockchain-btc",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Bitcoin blockchain adapter for CryptForge SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"author": "Viktor Albus",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"bitcoin",
|
|
20
|
+
"btc",
|
|
21
|
+
"cryptocurrency",
|
|
22
|
+
"blockchain",
|
|
23
|
+
"wallet",
|
|
24
|
+
"cryptforge"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/viktor-albus/cryptforge-sdk.git",
|
|
29
|
+
"directory": "packages/blockchain-btc"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/viktor-albus/cryptforge-sdk#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/viktor-albus/cryptforge-sdk/issues"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"dev": "tsup --watch"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@scure/base": "^1.1.3",
|
|
45
|
+
"@scure/bip32": "^1.3.2",
|
|
46
|
+
"@scure/bip39": "^1.2.1",
|
|
47
|
+
"@scure/btc-signer": "^1.2.1",
|
|
48
|
+
"@noble/hashes": "^1.3.3",
|
|
49
|
+
"@noble/secp256k1": "^2.0.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"@cryptforge/core": "^0.1.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@cryptforge/core": "^0.1.0",
|
|
56
|
+
"tsup": "^8.0.1",
|
|
57
|
+
"typescript": "^5.3.3"
|
|
58
|
+
}
|
|
59
|
+
}
|