@shapeshiftoss/hdwallet-gridplus 1.62.10 → 1.62.12

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/src/ethereum.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Common, Hardfork } from "@ethereumjs/common";
2
- import { TransactionFactory, TypedTxData } from "@ethereumjs/tx";
2
+ import { RLP } from "@ethereumjs/rlp";
3
+ import { TransactionFactory, TransactionType, TypedTxData } from "@ethereumjs/tx";
3
4
  import * as core from "@shapeshiftoss/hdwallet-core";
4
5
  import { Client, Constants, Utils } from "gridplus-sdk";
5
- import { encode } from "rlp";
6
6
 
7
7
  export async function ethGetAddress(client: Client, msg: core.ETHGetAddress): Promise<core.Address | null> {
8
8
  const address = (await client.getAddresses({ startPath: msg.addressNList, n: 1 }))[0];
@@ -23,37 +23,23 @@ export async function ethSignTx(client: Client, msg: core.ETHSignTx): Promise<co
23
23
  nonce: msg.nonce,
24
24
  gasLimit: msg.gasLimit,
25
25
  chainId: msg.chainId,
26
- // Add explicit type field for TransactionFactory to correctly detect transaction type
27
- type: isEIP1559 ? 2 : 0,
28
- ...(isEIP1559
29
- ? {
30
- maxFeePerGas: msg.maxFeePerGas,
31
- maxPriorityFeePerGas: msg.maxPriorityFeePerGas,
32
- }
33
- : {
34
- gasPrice: msg.gasPrice,
35
- }),
26
+ type: isEIP1559 ? TransactionType.FeeMarketEIP1559 : TransactionType.Legacy,
27
+ maxFeePerGas: msg.maxFeePerGas,
28
+ maxPriorityFeePerGas: msg.maxPriorityFeePerGas,
29
+ gasPrice: msg.gasPrice,
36
30
  };
37
31
 
38
- const common = isEIP1559
39
- ? Common.custom({ chainId: msg.chainId }, { hardfork: Hardfork.London })
40
- : Common.custom({ chainId: msg.chainId });
41
-
42
- // Use TransactionFactory with explicit type field (Kevin's approach)
32
+ const common = Common.custom({ chainId: msg.chainId }, { hardfork: Hardfork.London });
43
33
  const unsignedTx = TransactionFactory.fromTxData(txData, { common });
44
34
 
45
- // Handle payload encoding based on transaction type
46
- // Legacy transactions return an array that needs RLP encoding
47
- // EIP-1559 transactions return a pre-encoded buffer
48
- const rawPayload = unsignedTx.getMessageToSign();
49
- const payload = Array.isArray(rawPayload) ? encode(rawPayload) : rawPayload;
35
+ const payload = isEIP1559 ? unsignedTx.getMessageToSign() : RLP.encode(unsignedTx.getMessageToSign());
50
36
 
51
37
  const fwVersion = client.getFwVersion();
52
38
  const supportsDecoderRecursion = fwVersion.major > 0 || fwVersion.minor >= 16;
53
39
 
54
40
  const decoderResult = await (() => {
55
41
  if (!msg.data || (msg.data.startsWith("0x") && Buffer.from(msg.data.slice(2), "hex").length < 4)) {
56
- return { def: null };
42
+ return { def: undefined };
57
43
  }
58
44
  return Utils.fetchCalldataDecoder(msg.data, msg.to, msg.chainId, supportsDecoderRecursion);
59
45
  })();
@@ -67,7 +53,7 @@ export async function ethSignTx(client: Client, msg: core.ETHSignTx): Promise<co
67
53
  hashType: Constants.SIGNING.HASHES.KECCAK256,
68
54
  encodingType: Constants.SIGNING.ENCODINGS.EVM,
69
55
  signerPath: msg.addressNList,
70
- decoder: def,
56
+ decoder: def ? Buffer.from(def) : undefined,
71
57
  },
72
58
  });
73
59
 
@@ -79,29 +65,7 @@ export async function ethSignTx(client: Client, msg: core.ETHSignTx): Promise<co
79
65
  if (!Buffer.isBuffer(s)) throw new Error("Invalid signature (s)");
80
66
  if (!Buffer.isBuffer(v)) throw new Error("Invalid signature (v)");
81
67
 
82
- // Reconstruct signed transaction using TransactionFactory with explicit type field
83
- const signedTxData = {
84
- to: msg.to,
85
- value: msg.value,
86
- data: msg.data,
87
- nonce: msg.nonce,
88
- gasLimit: msg.gasLimit,
89
- chainId: msg.chainId,
90
- type: isEIP1559 ? 2 : 0,
91
- r,
92
- s,
93
- v,
94
- ...(isEIP1559
95
- ? {
96
- maxFeePerGas: msg.maxFeePerGas,
97
- maxPriorityFeePerGas: msg.maxPriorityFeePerGas,
98
- }
99
- : {
100
- gasPrice: msg.gasPrice,
101
- }),
102
- };
103
-
104
- const signedTx = TransactionFactory.fromTxData(signedTxData, { common });
68
+ const signedTx = TransactionFactory.fromTxData({ ...txData, r, s, v }, { common });
105
69
  const serialized = `0x${Buffer.from(signedTx.serialize()).toString("hex")}`;
106
70
 
107
71
  return { r: `0x${r.toString("hex")}`, s: `0x${s.toString("hex")}`, v: v.readUIntBE(0, v.length), serialized };
package/src/gridplus.ts CHANGED
@@ -8,8 +8,8 @@ import * as eth from "./ethereum";
8
8
  import * as mayachain from "./mayachain";
9
9
  import * as solana from "./solana";
10
10
  import * as thorchain from "./thorchain";
11
- import { GridPlusTransport } from "./transport";
12
- import { convertXpubVersion, scriptTypeToAccountType } from "./utils";
11
+
12
+ const ZERO_BUFFER = Buffer.alloc(32);
13
13
 
14
14
  export function isGridPlus(wallet: core.HDWallet): wallet is GridPlusHDWallet {
15
15
  return isObject(wallet) && (wallet as any)._isGridPlus;
@@ -273,12 +273,12 @@ export class GridPlusHDWallet
273
273
  extends GridPlusWalletInfo
274
274
  implements
275
275
  core.HDWallet,
276
- core.ETHWallet,
277
- core.SolanaWallet,
278
276
  core.BTCWallet,
279
277
  core.CosmosWallet,
280
- core.ThorchainWallet,
281
- core.MayachainWallet
278
+ core.ETHWallet,
279
+ core.MayachainWallet,
280
+ core.SolanaWallet,
281
+ core.ThorchainWallet
282
282
  {
283
283
  readonly _supportsArbitrum = true;
284
284
  readonly _supportsArbitrumNova = false;
@@ -298,117 +298,80 @@ export class GridPlusHDWallet
298
298
 
299
299
  readonly _isGridPlus = true;
300
300
 
301
- private activeWalletId?: string;
302
-
303
- transport: GridPlusTransport;
304
- client?: Client;
301
+ client: Client | undefined;
305
302
 
306
- constructor(transport: GridPlusTransport) {
303
+ constructor(client: Client) {
307
304
  super();
308
- this.transport = transport;
309
- }
310
-
311
- public setActiveWalletId(walletId: string): void {
312
- this.activeWalletId = walletId;
305
+ this.client = client;
306
+ }
307
+
308
+ async cancel(): Promise<void> {}
309
+ async clearSession(): Promise<void> {}
310
+ async initialize(): Promise<void> {}
311
+ async loadDevice(): Promise<void> {}
312
+ async recover(): Promise<void> {}
313
+ async reset(): Promise<void> {}
314
+ async sendCharacter(): Promise<void> {}
315
+ async sendPassphrase(): Promise<void> {}
316
+ async sendPin(): Promise<void> {}
317
+ async sendWord(): Promise<void> {}
318
+ async wipe(): Promise<void> {}
319
+
320
+ async getDeviceID(): Promise<string> {
321
+ if (!this.client) throw new Error("Device not connected");
322
+ return this.client.getDeviceId();
313
323
  }
314
324
 
315
325
  async getFeatures(): Promise<Record<string, any>> {
326
+ if (!this.client) throw new Error("Device not connected");
327
+
316
328
  return {
317
329
  vendor: "GridPlus",
318
- deviceId: this.transport.deviceId,
330
+ deviceId: this.client.getDeviceId(),
319
331
  model: "Lattice1",
320
332
  };
321
333
  }
322
334
 
323
- public async isLocked(): Promise<boolean> {
324
- return !this.transport.isConnected();
325
- }
326
-
327
- public async clearSession(): Promise<void> {
328
- if (!this.client) return;
329
- await this.transport.disconnect();
330
- this.client = undefined;
331
- }
332
-
333
- public async isInitialized(): Promise<boolean> {
334
- return !!this.client;
335
- }
336
-
337
- public async initialize(): Promise<void> {
338
- // Get the GridPlus client from transport after successful pairing
339
- this.client = this.transport.getClient();
340
-
341
- if (!this.client) {
342
- throw new Error("GridPlus client not available - device may not be paired");
343
- }
344
-
345
- // Validate that the client has the expected methods
346
- if (typeof this.client.getAddresses !== "function") {
347
- throw new Error("GridPlus client missing required getAddresses method");
348
- }
349
- }
350
-
351
- public async ping(msg: core.Ping): Promise<core.Pong> {
352
- return { msg: msg.msg };
353
- }
354
-
355
- public async sendPin(): Promise<void> {}
356
-
357
- public async sendPassphrase(): Promise<void> {}
358
-
359
- public async sendCharacter(): Promise<void> {}
360
-
361
- public async sendWord(): Promise<void> {}
362
-
363
- public async cancel(): Promise<void> {
364
- // GridPlus has no pending device interactions to cancel
365
- // Wallet persists in keyring - do not disconnect
366
- }
367
-
368
- public async wipe(): Promise<void> {
369
- throw new Error("GridPlus does not support wiping");
335
+ async getFirmwareVersion(): Promise<string> {
336
+ if (!this.client) throw new Error("Device not connected");
337
+ const { major, minor, fix } = this.client.getFwVersion();
338
+ return `${major}.${minor}.${fix}`;
370
339
  }
371
340
 
372
- public async reset(): Promise<void> {
373
- await this.clearSession();
374
- await this.initialize();
341
+ async getModel(): Promise<string> {
342
+ return "Lattice1";
375
343
  }
376
344
 
377
- public async recover(): Promise<void> {
378
- throw new Error("GridPlus does not support recovery mode");
345
+ async getLabel(): Promise<string> {
346
+ return "GridPlus Lattice1";
379
347
  }
380
348
 
381
- public async loadDevice(): Promise<void> {
382
- throw new Error("GridPlus does not support device loading");
349
+ async isInitialized(): Promise<boolean> {
350
+ return Boolean(this.client);
383
351
  }
384
352
 
385
- public describePath(): core.PathDescription {
386
- return {
387
- verbose: "GridPlus does not support path descriptions yet",
388
- coin: "Unknown",
389
- isKnown: false,
390
- };
353
+ async isLocked(): Promise<boolean> {
354
+ return false;
391
355
  }
392
356
 
393
- public async getModel(): Promise<string> {
394
- return "Lattice1";
357
+ async ping(msg: core.Ping): Promise<core.Pong> {
358
+ return { msg: msg.msg };
395
359
  }
396
360
 
397
- public async getLabel(): Promise<string> {
398
- return "GridPlus Lattice1";
361
+ async disconnect(): Promise<void> {
362
+ this.client = undefined;
399
363
  }
400
364
 
401
- public async getFirmwareVersion(): Promise<string> {
365
+ async getActiveWalletId(): Promise<string | undefined> {
402
366
  if (!this.client) throw new Error("Device not connected");
403
- const { major, minor, fix } = this.client.getFwVersion();
404
- return `${major}.${minor}.${fix}`;
405
- }
406
367
 
407
- public async getDeviceID(): Promise<string> {
408
- return this.activeWalletId || (await this.transport.getDeviceID());
368
+ const { external, internal } = await this.client.fetchActiveWallet();
369
+
370
+ if (!external.uid.equals(ZERO_BUFFER)) return external.uid.toString("hex");
371
+ if (!internal.uid.equals(ZERO_BUFFER)) return internal.uid.toString("hex");
409
372
  }
410
373
 
411
- public async getPublicKeys(msg: Array<core.GetPublicKey>): Promise<Array<core.PublicKey | null>> {
374
+ async getPublicKeys(msg: Array<core.GetPublicKey>): Promise<Array<core.PublicKey | null>> {
412
375
  if (!this.client) throw new Error("Device not connected");
413
376
 
414
377
  const publicKeys: Array<core.PublicKey | null> = [];
@@ -417,18 +380,18 @@ export class GridPlusHDWallet
417
380
  const { addressNList, curve, coin, scriptType } = getPublicKey;
418
381
 
419
382
  try {
420
- let flag: number;
421
-
422
- // Determine the appropriate flag based on curve type
423
- if (curve === "secp256k1") {
424
- // For UTXO chains (Bitcoin, Dogecoin), we need the xpub
425
- flag = Constants.GET_ADDR_FLAGS.SECP256K1_XPUB;
426
- } else if (curve === "ed25519") {
427
- // For Solana/ed25519 chains, we need the public key
428
- flag = Constants.GET_ADDR_FLAGS.ED25519_PUB;
429
- } else {
430
- throw new Error(`Unsupported curve: ${curve}`);
431
- }
383
+ const flag = (() => {
384
+ switch (curve) {
385
+ // For UTXO chains (Bitcoin, Dogecoin), we need the xpub
386
+ case "secp256k1":
387
+ return Constants.GET_ADDR_FLAGS.SECP256K1_XPUB;
388
+ // For Solana/ed25519 chains, we need the public key
389
+ case "ed25519":
390
+ return Constants.GET_ADDR_FLAGS.ED25519_PUB;
391
+ default:
392
+ throw new Error(`Unsupported curve: ${curve}`);
393
+ }
394
+ })();
432
395
 
433
396
  const addresses = await this.client!.getAddresses({
434
397
  startPath: addressNList,
@@ -436,17 +399,15 @@ export class GridPlusHDWallet
436
399
  flag,
437
400
  });
438
401
 
439
- if (!addresses.length) {
440
- throw new Error("No public key returned from device");
441
- }
402
+ if (!addresses.length) throw new Error("No public key returned from device");
442
403
 
443
404
  // addresses[0] contains either xpub string (for SECP256K1_XPUB) or pubkey hex (for ED25519_PUB)
444
405
  let xpub = typeof addresses[0] === "string" ? addresses[0] : Buffer.from(addresses[0]).toString("hex");
445
406
 
446
407
  // Convert xpub format for Dogecoin/Litecoin (GridPlus returns Bitcoin xpub format)
447
408
  if (coin && curve === "secp256k1") {
448
- const accountType = scriptTypeToAccountType(scriptType);
449
- xpub = convertXpubVersion(xpub, accountType, coin);
409
+ const accountType = scriptType ? core.scriptTypeToAccountType[scriptType] : undefined;
410
+ xpub = core.convertXpubVersion(xpub, accountType, coin);
450
411
  }
451
412
 
452
413
  publicKeys.push({ xpub });
@@ -458,53 +419,45 @@ export class GridPlusHDWallet
458
419
  return publicKeys;
459
420
  }
460
421
 
461
- public getSessionId(): string | undefined {
462
- return this.transport.getSessionId();
463
- }
464
-
465
- public async disconnect(): Promise<void> {
466
- await this.clearSession();
467
- }
468
-
469
- public async btcGetAddress(msg: core.BTCGetAddress): Promise<string | null> {
422
+ async btcGetAddress(msg: core.BTCGetAddress): Promise<string | null> {
470
423
  if (!this.client) throw new Error("Device not connected");
471
424
  return btc.btcGetAddress(this.client!, msg);
472
425
  }
473
426
 
474
- public async btcSignTx(msg: core.BTCSignTx): Promise<core.BTCSignedTx | null> {
427
+ async btcSignTx(msg: core.BTCSignTx): Promise<core.BTCSignedTx | null> {
475
428
  if (!this.client) throw new Error("Device not connected");
476
429
  return btc.btcSignTx(this.client, msg);
477
430
  }
478
431
 
479
- public async btcSignMessage(): Promise<core.BTCSignedMessage | null> {
432
+ async btcSignMessage(): Promise<core.BTCSignedMessage | null> {
480
433
  throw new Error("GridPlus BTC message signing not yet implemented");
481
434
  }
482
435
 
483
- public async btcVerifyMessage(): Promise<boolean | null> {
436
+ async btcVerifyMessage(): Promise<boolean | null> {
484
437
  throw new Error("GridPlus BTC message verification not yet implemented");
485
438
  }
486
439
 
487
- public async ethGetAddress(msg: core.ETHGetAddress): Promise<core.Address | null> {
440
+ async ethGetAddress(msg: core.ETHGetAddress): Promise<core.Address | null> {
488
441
  if (!this.client) throw new Error("Device not connected");
489
442
  return eth.ethGetAddress(this.client, msg);
490
443
  }
491
444
 
492
- public async ethSignTx(msg: core.ETHSignTx): Promise<core.ETHSignedTx> {
445
+ async ethSignTx(msg: core.ETHSignTx): Promise<core.ETHSignedTx> {
493
446
  if (!this.client) throw new Error("Device not connected");
494
447
  return eth.ethSignTx(this.client, msg);
495
448
  }
496
449
 
497
- public async ethSignTypedData(msg: core.ETHSignTypedData): Promise<core.ETHSignedTypedData> {
450
+ async ethSignTypedData(msg: core.ETHSignTypedData): Promise<core.ETHSignedTypedData> {
498
451
  if (!this.client) throw new Error("Device not connected");
499
452
  return eth.ethSignTypedData(this.client, msg);
500
453
  }
501
454
 
502
- public async ethSignMessage(msg: core.ETHSignMessage): Promise<core.ETHSignedMessage> {
455
+ async ethSignMessage(msg: core.ETHSignMessage): Promise<core.ETHSignedMessage> {
503
456
  if (!this.client) throw new Error("Device not connected");
504
457
  return eth.ethSignMessage(this.client, msg);
505
458
  }
506
459
 
507
- public async ethVerifyMessage(): Promise<boolean> {
460
+ async ethVerifyMessage(): Promise<boolean> {
508
461
  throw new Error("GridPlus ETH message verification not implemented yet");
509
462
  }
510
463
 
@@ -520,42 +473,42 @@ export class GridPlusHDWallet
520
473
  }
521
474
  }
522
475
 
523
- public async solanaGetAddress(msg: core.SolanaGetAddress): Promise<string | null> {
476
+ async solanaGetAddress(msg: core.SolanaGetAddress): Promise<string | null> {
524
477
  this.assertSolanaFwSupport();
525
478
  return solana.solanaGetAddress(this.client, msg);
526
479
  }
527
480
 
528
- public async solanaSignTx(msg: core.SolanaSignTx): Promise<core.SolanaSignedTx | null> {
481
+ async solanaSignTx(msg: core.SolanaSignTx): Promise<core.SolanaSignedTx | null> {
529
482
  this.assertSolanaFwSupport();
530
483
  return solana.solanaSignTx(this.client, msg);
531
484
  }
532
485
 
533
- public async cosmosGetAddress(msg: core.CosmosGetAddress): Promise<string | null> {
486
+ async cosmosGetAddress(msg: core.CosmosGetAddress): Promise<string | null> {
534
487
  if (!this.client) throw new Error("Device not connected");
535
488
  return cosmos.cosmosGetAddress(this.client, msg);
536
489
  }
537
490
 
538
- public async cosmosSignTx(msg: core.CosmosSignTx): Promise<core.CosmosSignedTx | null> {
491
+ async cosmosSignTx(msg: core.CosmosSignTx): Promise<core.CosmosSignedTx | null> {
539
492
  if (!this.client) throw new Error("Device not connected");
540
493
  return cosmos.cosmosSignTx(this.client, msg);
541
494
  }
542
495
 
543
- public async thorchainGetAddress(msg: core.ThorchainGetAddress): Promise<string | null> {
496
+ async thorchainGetAddress(msg: core.ThorchainGetAddress): Promise<string | null> {
544
497
  if (!this.client) throw new Error("Device not connected");
545
498
  return thorchain.thorchainGetAddress(this.client, msg);
546
499
  }
547
500
 
548
- public async thorchainSignTx(msg: core.ThorchainSignTx): Promise<core.ThorchainSignedTx | null> {
501
+ async thorchainSignTx(msg: core.ThorchainSignTx): Promise<core.ThorchainSignedTx | null> {
549
502
  if (!this.client) throw new Error("Device not connected");
550
503
  return thorchain.thorchainSignTx(this.client, msg);
551
504
  }
552
505
 
553
- public async mayachainGetAddress(msg: core.MayachainGetAddress): Promise<string | null> {
506
+ async mayachainGetAddress(msg: core.MayachainGetAddress): Promise<string | null> {
554
507
  if (!this.client) throw new Error("Device not connected");
555
508
  return mayachain.mayachainGetAddress(this.client, msg);
556
509
  }
557
510
 
558
- public async mayachainSignTx(msg: core.MayachainSignTx): Promise<core.MayachainSignedTx | null> {
511
+ async mayachainSignTx(msg: core.MayachainSignTx): Promise<core.MayachainSignedTx | null> {
559
512
  if (!this.client) throw new Error("Device not connected");
560
513
  return mayachain.mayachainSignTx(this.client, msg);
561
514
  }
package/src/index.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  export * from "./adapter";
2
2
  export { GridPlusHDWallet, GridPlusWalletInfo, isGridPlus } from "./gridplus";
3
- export * from "./transport";
package/src/utils.ts CHANGED
@@ -1,14 +1,11 @@
1
1
  import { pointCompress } from "@bitcoinerlab/secp256k1";
2
- import * as core from "@shapeshiftoss/hdwallet-core";
3
2
  import * as bech32 from "bech32";
4
- import { decode as bs58Decode, encode as bs58Encode } from "bs58check";
3
+ import * as bs58 from "bs58check";
5
4
  import CryptoJS from "crypto-js";
6
5
 
7
- import { accountTypeToVersion, convertVersions, UTXO_NETWORK_PARAMS, UtxoAccountType } from "./constants";
8
-
9
6
  export const getCompressedPubkey = (pubkey: string | Buffer): Buffer => {
10
7
  // Extended public key (xpub/ypub/zpub)
11
- if (typeof pubkey === "string") return bs58Decode(pubkey).subarray(45, 78);
8
+ if (typeof pubkey === "string") return bs58.decode(pubkey).subarray(45, 78);
12
9
 
13
10
  // Already compressed public key (33 bytes)
14
11
  if (pubkey.length === 33) return pubkey;
@@ -27,98 +24,3 @@ export const createBech32Address = (pubkey: string | Buffer, prefix: string): st
27
24
  const words = bech32.toWords(address);
28
25
  return bech32.encode(prefix, words);
29
26
  };
30
-
31
- /**
32
- * Convert xpub version bytes for different coins (e.g., xpub → dgub for Dogecoin)
33
- * GridPlus returns Bitcoin-format xpubs, but some coins like Dogecoin need different prefixes
34
- */
35
- export function convertXpubVersion(xpub: string, accountType: UtxoAccountType | undefined, coin: string): string {
36
- if (!accountType) return xpub;
37
- if (!convertVersions.includes(xpub.substring(0, 4))) {
38
- return xpub;
39
- }
40
-
41
- const payload = bs58Decode(xpub);
42
- const version = payload.slice(0, 4);
43
- const desiredVersion = accountTypeToVersion(coin, accountType);
44
- if (version.compare(desiredVersion) !== 0) {
45
- const key = payload.slice(4);
46
- return bs58Encode(Buffer.concat([desiredVersion, key]));
47
- }
48
- return xpub;
49
- }
50
-
51
- export function scriptTypeToAccountType(scriptType: core.BTCInputScriptType | undefined): UtxoAccountType | undefined {
52
- switch (scriptType) {
53
- case core.BTCInputScriptType.SpendAddress:
54
- return UtxoAccountType.P2pkh;
55
- case core.BTCInputScriptType.SpendWitness:
56
- return UtxoAccountType.SegwitNative;
57
- case core.BTCInputScriptType.SpendP2SHWitness:
58
- return UtxoAccountType.SegwitP2sh;
59
- default:
60
- return undefined;
61
- }
62
- }
63
-
64
- /**
65
- * Derive a UTXO address from a compressed public key
66
- * @param pubkeyHex - Compressed public key as hex string (33 bytes, starting with 02 or 03)
67
- * @param coin - Coin name (Bitcoin, Dogecoin, Litecoin, etc.)
68
- * @param scriptType - Script type (p2pkh, p2wpkh, p2sh-p2wpkh)
69
- * @returns The derived address
70
- */
71
- export function deriveAddressFromPubkey(
72
- pubkeyHex: string,
73
- coin: string,
74
- scriptType: core.BTCInputScriptType = core.BTCInputScriptType.SpendAddress
75
- ): string {
76
- const network = UTXO_NETWORK_PARAMS[coin] || UTXO_NETWORK_PARAMS.Bitcoin;
77
- const pubkeyBuffer = Buffer.from(pubkeyHex, "hex");
78
-
79
- if (pubkeyBuffer.length !== 33) {
80
- throw new Error(`Invalid compressed public key length: ${pubkeyBuffer.length} bytes`);
81
- }
82
-
83
- // Hash160 = RIPEMD160(SHA256(pubkey))
84
- const sha256Hash = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(pubkeyHex));
85
- const hash160 = CryptoJS.RIPEMD160(sha256Hash).toString();
86
- const hash160Buffer = Buffer.from(hash160, "hex");
87
-
88
- switch (scriptType) {
89
- case core.BTCInputScriptType.SpendAddress: {
90
- // P2PKH: <pubKeyHash version byte> + hash160 + checksum
91
- const payload = Buffer.concat([Buffer.from([network.pubKeyHash]), hash160Buffer]);
92
- return bs58Encode(payload);
93
- }
94
-
95
- case core.BTCInputScriptType.SpendWitness: {
96
- // P2WPKH (bech32): witness version 0 + hash160
97
- if (!network.bech32) {
98
- throw new Error(`Bech32 not supported for ${coin}`);
99
- }
100
- const words = bech32.toWords(hash160Buffer);
101
- words.unshift(0); // witness version 0
102
- return bech32.encode(network.bech32, words);
103
- }
104
-
105
- case core.BTCInputScriptType.SpendP2SHWitness: {
106
- // P2SH-P2WPKH: scriptHash of witness program
107
- // Witness program: OP_0 (0x00) + length (0x14) + hash160
108
- const witnessProgram = Buffer.concat([Buffer.from([0x00, 0x14]), hash160Buffer]);
109
-
110
- // Hash160 of witness program
111
- const wpHex = witnessProgram.toString("hex");
112
- const wpSha256 = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(wpHex));
113
- const wpHash160 = CryptoJS.RIPEMD160(wpSha256).toString();
114
- const wpHash160Buffer = Buffer.from(wpHash160, "hex");
115
-
116
- // Encode with scriptHash version byte
117
- const payload = Buffer.concat([Buffer.from([network.scriptHash]), wpHash160Buffer]);
118
- return bs58Encode(payload);
119
- }
120
-
121
- default:
122
- throw new Error(`Unsupported script type: ${scriptType}`);
123
- }
124
- }
package/tsconfig.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "extends": "../../tsconfig.json",
3
3
  "compilerOptions": {
4
+ "rootDir": "src",
4
5
  "outDir": "dist",
5
- "rootDir": "src"
6
+ "tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo",
6
7
  },
7
8
  "include": ["src/**/*"],
8
9
  "exclude": ["node_modules", "dist"],
@@ -1,28 +0,0 @@
1
- import * as core from "@shapeshiftoss/hdwallet-core";
2
- import { Client } from "gridplus-sdk";
3
- export type GridPlusTransportConfig = {
4
- deviceId: string;
5
- password?: string;
6
- };
7
- export declare class GridPlusTransport extends core.Transport {
8
- deviceId?: string;
9
- password?: string;
10
- connected: boolean;
11
- private client?;
12
- private sessionId?;
13
- constructor(config: GridPlusTransportConfig);
14
- getDeviceID(): Promise<string>;
15
- connect(): Promise<void>;
16
- connectGridPlus(deviceId: string, password?: string): Promise<void>;
17
- disconnect(): Promise<void>;
18
- isConnected(): boolean;
19
- setup(deviceId: string, password?: string, existingSessionId?: string): Promise<{
20
- isPaired: boolean;
21
- sessionId: string;
22
- }>;
23
- pair(pairingCode: string): Promise<boolean>;
24
- getClient(): Client | undefined;
25
- getSessionId(): string | undefined;
26
- call(): Promise<any>;
27
- }
28
- //# sourceMappingURL=transport.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,8BAA8B,CAAC;AAErD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,IAAI,CAAC,SAAS;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAS;IAClC,OAAO,CAAC,MAAM,CAAC,CAAS;IAIxB,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,MAAM,EAAE,uBAAuB;IAMpC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAYxB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,WAAW,IAAI,OAAO;IAIhB,KAAK,CAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAgDvC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUjD,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B,YAAY,IAAI,MAAM,GAAG,SAAS;IAI5B,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;CAGlC"}