@shapeshiftoss/hdwallet-gridplus 1.62.4-gridplus.alpha.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE.md +21 -0
  3. package/dist/adapter.d.ts +19 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +129 -0
  6. package/dist/adapter.js.map +1 -0
  7. package/dist/bitcoin.d.ts +7 -0
  8. package/dist/bitcoin.d.ts.map +1 -0
  9. package/dist/bitcoin.js +619 -0
  10. package/dist/bitcoin.js.map +1 -0
  11. package/dist/constants.d.ts +18 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +51 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/cosmos.d.ts +7 -0
  16. package/dist/cosmos.d.ts.map +1 -0
  17. package/dist/cosmos.js +156 -0
  18. package/dist/cosmos.js.map +1 -0
  19. package/dist/ethereum.d.ts +7 -0
  20. package/dist/ethereum.d.ts.map +1 -0
  21. package/dist/ethereum.js +294 -0
  22. package/dist/ethereum.js.map +1 -0
  23. package/dist/gridplus.d.ts +112 -0
  24. package/dist/gridplus.d.ts.map +1 -0
  25. package/dist/gridplus.js +574 -0
  26. package/dist/gridplus.js.map +1 -0
  27. package/dist/index.d.ts +4 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +24 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/mayachain.d.ts +7 -0
  32. package/dist/mayachain.d.ts.map +1 -0
  33. package/dist/mayachain.js +163 -0
  34. package/dist/mayachain.js.map +1 -0
  35. package/dist/solana.d.ts +5 -0
  36. package/dist/solana.d.ts.map +1 -0
  37. package/dist/solana.js +120 -0
  38. package/dist/solana.js.map +1 -0
  39. package/dist/thorchain.d.ts +5 -0
  40. package/dist/thorchain.d.ts.map +1 -0
  41. package/dist/thorchain.js +143 -0
  42. package/dist/thorchain.js.map +1 -0
  43. package/dist/transport.d.ts +28 -0
  44. package/dist/transport.d.ts.map +1 -0
  45. package/dist/transport.js +148 -0
  46. package/dist/transport.js.map +1 -0
  47. package/dist/utils.d.ts +17 -0
  48. package/dist/utils.d.ts.map +1 -0
  49. package/dist/utils.js +117 -0
  50. package/dist/utils.js.map +1 -0
  51. package/package.json +38 -0
  52. package/package.json.bak +38 -0
  53. package/src/adapter.ts +109 -0
  54. package/src/bitcoin.ts +711 -0
  55. package/src/constants.ts +52 -0
  56. package/src/cosmos.ts +132 -0
  57. package/src/ethereum.ts +305 -0
  58. package/src/gridplus.ts +550 -0
  59. package/src/index.ts +3 -0
  60. package/src/mayachain.ts +150 -0
  61. package/src/solana.ts +97 -0
  62. package/src/thorchain.ts +125 -0
  63. package/src/transport.ts +131 -0
  64. package/src/utils.ts +101 -0
  65. package/tsconfig.json +10 -0
  66. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.GridPlusTransport = void 0;
36
+ const core = __importStar(require("@shapeshiftoss/hdwallet-core"));
37
+ const crypto_1 = require("crypto");
38
+ const gridplus_sdk_1 = require("gridplus-sdk");
39
+ class GridPlusTransport extends core.Transport {
40
+ constructor(config) {
41
+ super(new core.Keyring());
42
+ this.connected = false;
43
+ this.deviceId = config.deviceId;
44
+ this.password = config.password;
45
+ }
46
+ getDeviceID() {
47
+ return Promise.resolve(this.deviceId || "");
48
+ }
49
+ connect() {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ if (!this.deviceId) {
52
+ throw new Error("Device ID is required to connect to GridPlus");
53
+ }
54
+ const { isPaired } = yield this.setup(this.deviceId, this.password);
55
+ if (!isPaired) {
56
+ throw new Error("Device is not paired");
57
+ }
58
+ });
59
+ }
60
+ connectGridPlus(deviceId, password) {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ this.deviceId = deviceId;
63
+ this.password = password || "shapeshift-default";
64
+ yield this.connect();
65
+ });
66
+ }
67
+ disconnect() {
68
+ return __awaiter(this, void 0, void 0, function* () {
69
+ this.connected = false;
70
+ this.deviceId = undefined;
71
+ this.password = undefined;
72
+ });
73
+ }
74
+ isConnected() {
75
+ return this.connected;
76
+ }
77
+ setup(deviceId, password, existingSessionId) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ this.deviceId = deviceId;
80
+ this.password = password || "shapeshift-default";
81
+ // Use existing sessionId if provided, otherwise generate new one
82
+ if (existingSessionId) {
83
+ this.sessionId = existingSessionId;
84
+ }
85
+ else if (!this.sessionId) {
86
+ this.sessionId = (0, crypto_1.randomBytes)(32).toString("hex");
87
+ }
88
+ // Create Client instance directly (Frame pattern) - no localStorage!
89
+ // This ensures we always get fresh activeWallets from device
90
+ if (!this.client) {
91
+ this.client = new gridplus_sdk_1.Client({
92
+ name: "ShapeShift",
93
+ baseUrl: "https://signing.gridpl.us",
94
+ privKey: Buffer.from(this.sessionId, "hex"),
95
+ retryCount: 3,
96
+ timeout: 60000,
97
+ skipRetryOnWrongWallet: true,
98
+ });
99
+ try {
100
+ // Connect to device - returns true if paired, false if needs pairing
101
+ const isPaired = yield this.client.connect(deviceId);
102
+ this.connected = true;
103
+ return { isPaired, sessionId: this.sessionId };
104
+ }
105
+ catch (error) {
106
+ // Handle "Device Locked" error - treat as unpaired
107
+ const errorMessage = error instanceof Error ? error.message : String(error);
108
+ if (errorMessage.toLowerCase().includes("device locked")) {
109
+ this.connected = true;
110
+ return { isPaired: false, sessionId: this.sessionId };
111
+ }
112
+ throw error;
113
+ }
114
+ }
115
+ else {
116
+ // Client already exists, reset active wallets to clear stale state before reconnecting
117
+ // This is critical when switching between SafeCards - ensures fresh wallet state from device
118
+ this.client.resetActiveWallets();
119
+ const isPaired = yield this.client.connect(deviceId);
120
+ this.connected = true;
121
+ return { isPaired, sessionId: this.sessionId };
122
+ }
123
+ });
124
+ }
125
+ pair(pairingCode) {
126
+ return __awaiter(this, void 0, void 0, function* () {
127
+ if (!this.client) {
128
+ throw new Error("Client not initialized. Call setup() first.");
129
+ }
130
+ const result = yield this.client.pair(pairingCode);
131
+ this.connected = !!result;
132
+ return !!result;
133
+ });
134
+ }
135
+ getClient() {
136
+ return this.client;
137
+ }
138
+ getSessionId() {
139
+ return this.sessionId;
140
+ }
141
+ call() {
142
+ return __awaiter(this, void 0, void 0, function* () {
143
+ throw new Error("GridPlus transport call not implemented");
144
+ });
145
+ }
146
+ }
147
+ exports.GridPlusTransport = GridPlusTransport;
148
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import * as core from "@shapeshiftoss/hdwallet-core";
2
+ import { UtxoAccountType } from "./constants";
3
+ /**
4
+ * Convert xpub version bytes for different coins (e.g., xpub → dgub for Dogecoin)
5
+ * GridPlus returns Bitcoin-format xpubs, but some coins like Dogecoin need different prefixes
6
+ */
7
+ export declare function convertXpubVersion(xpub: string, accountType: UtxoAccountType | undefined, coin: string): string;
8
+ export declare function scriptTypeToAccountType(scriptType: core.BTCInputScriptType | undefined): UtxoAccountType | undefined;
9
+ /**
10
+ * Derive a UTXO address from a compressed public key
11
+ * @param pubkeyHex - Compressed public key as hex string (33 bytes, starting with 02 or 03)
12
+ * @param coin - Coin name (Bitcoin, Dogecoin, Litecoin, etc.)
13
+ * @param scriptType - Script type (p2pkh, p2wpkh, p2sh-p2wpkh)
14
+ * @returns The derived address
15
+ */
16
+ export declare function deriveAddressFromPubkey(pubkeyHex: string, coin: string, scriptType?: core.BTCInputScriptType): string;
17
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,8BAA8B,CAAC;AAKrD,OAAO,EAA8D,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1G;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAc/G;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,IAAI,CAAC,kBAAkB,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,CAWpH;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,IAAI,CAAC,kBAAyD,GACzE,MAAM,CAiDR"}
package/dist/utils.js ADDED
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.convertXpubVersion = convertXpubVersion;
30
+ exports.scriptTypeToAccountType = scriptTypeToAccountType;
31
+ exports.deriveAddressFromPubkey = deriveAddressFromPubkey;
32
+ const core = __importStar(require("@shapeshiftoss/hdwallet-core"));
33
+ const bech32 = __importStar(require("bech32"));
34
+ const bs58check_1 = require("bs58check");
35
+ const crypto_js_1 = __importDefault(require("crypto-js"));
36
+ const constants_1 = require("./constants");
37
+ /**
38
+ * Convert xpub version bytes for different coins (e.g., xpub → dgub for Dogecoin)
39
+ * GridPlus returns Bitcoin-format xpubs, but some coins like Dogecoin need different prefixes
40
+ */
41
+ function convertXpubVersion(xpub, accountType, coin) {
42
+ if (!accountType)
43
+ return xpub;
44
+ if (!constants_1.convertVersions.includes(xpub.substring(0, 4))) {
45
+ return xpub;
46
+ }
47
+ const payload = (0, bs58check_1.decode)(xpub);
48
+ const version = payload.slice(0, 4);
49
+ const desiredVersion = (0, constants_1.accountTypeToVersion)(coin, accountType);
50
+ if (version.compare(desiredVersion) !== 0) {
51
+ const key = payload.slice(4);
52
+ return (0, bs58check_1.encode)(Buffer.concat([desiredVersion, key]));
53
+ }
54
+ return xpub;
55
+ }
56
+ function scriptTypeToAccountType(scriptType) {
57
+ switch (scriptType) {
58
+ case core.BTCInputScriptType.SpendAddress:
59
+ return constants_1.UtxoAccountType.P2pkh;
60
+ case core.BTCInputScriptType.SpendWitness:
61
+ return constants_1.UtxoAccountType.SegwitNative;
62
+ case core.BTCInputScriptType.SpendP2SHWitness:
63
+ return constants_1.UtxoAccountType.SegwitP2sh;
64
+ default:
65
+ return undefined;
66
+ }
67
+ }
68
+ /**
69
+ * Derive a UTXO address from a compressed public key
70
+ * @param pubkeyHex - Compressed public key as hex string (33 bytes, starting with 02 or 03)
71
+ * @param coin - Coin name (Bitcoin, Dogecoin, Litecoin, etc.)
72
+ * @param scriptType - Script type (p2pkh, p2wpkh, p2sh-p2wpkh)
73
+ * @returns The derived address
74
+ */
75
+ function deriveAddressFromPubkey(pubkeyHex, coin, scriptType = core.BTCInputScriptType.SpendAddress) {
76
+ const network = constants_1.UTXO_NETWORK_PARAMS[coin] || constants_1.UTXO_NETWORK_PARAMS.Bitcoin;
77
+ const pubkeyBuffer = Buffer.from(pubkeyHex, "hex");
78
+ if (pubkeyBuffer.length !== 33) {
79
+ throw new Error(`Invalid compressed public key length: ${pubkeyBuffer.length} bytes`);
80
+ }
81
+ // Hash160 = RIPEMD160(SHA256(pubkey))
82
+ const sha256Hash = crypto_js_1.default.SHA256(crypto_js_1.default.enc.Hex.parse(pubkeyHex));
83
+ const hash160 = crypto_js_1.default.RIPEMD160(sha256Hash).toString();
84
+ const hash160Buffer = Buffer.from(hash160, "hex");
85
+ switch (scriptType) {
86
+ case core.BTCInputScriptType.SpendAddress: {
87
+ // P2PKH: <pubKeyHash version byte> + hash160 + checksum
88
+ const payload = Buffer.concat([Buffer.from([network.pubKeyHash]), hash160Buffer]);
89
+ return (0, bs58check_1.encode)(payload);
90
+ }
91
+ case core.BTCInputScriptType.SpendWitness: {
92
+ // P2WPKH (bech32): witness version 0 + hash160
93
+ if (!network.bech32) {
94
+ throw new Error(`Bech32 not supported for ${coin}`);
95
+ }
96
+ const words = bech32.toWords(hash160Buffer);
97
+ words.unshift(0); // witness version 0
98
+ return bech32.encode(network.bech32, words);
99
+ }
100
+ case core.BTCInputScriptType.SpendP2SHWitness: {
101
+ // P2SH-P2WPKH: scriptHash of witness program
102
+ // Witness program: OP_0 (0x00) + length (0x14) + hash160
103
+ const witnessProgram = Buffer.concat([Buffer.from([0x00, 0x14]), hash160Buffer]);
104
+ // Hash160 of witness program
105
+ const wpHex = witnessProgram.toString("hex");
106
+ const wpSha256 = crypto_js_1.default.SHA256(crypto_js_1.default.enc.Hex.parse(wpHex));
107
+ const wpHash160 = crypto_js_1.default.RIPEMD160(wpSha256).toString();
108
+ const wpHash160Buffer = Buffer.from(wpHash160, "hex");
109
+ // Encode with scriptHash version byte
110
+ const payload = Buffer.concat([Buffer.from([network.scriptHash]), wpHash160Buffer]);
111
+ return (0, bs58check_1.encode)(payload);
112
+ }
113
+ default:
114
+ throw new Error(`Unsupported script type: ${scriptType}`);
115
+ }
116
+ }
117
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@shapeshiftoss/hdwallet-gridplus",
3
+ "version": "1.62.4-gridplus.alpha.0",
4
+ "license": "MIT",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "dist/index.js",
9
+ "source": "src/index.ts",
10
+ "types": "dist/index.d.ts",
11
+ "scripts": {
12
+ "build": "tsc --build",
13
+ "build:docs": "typedoc --out docs --target es6 --theme minimal --mode file src",
14
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
15
+ "prepublishOnly": "yarn clean && yarn build"
16
+ },
17
+ "dependencies": {
18
+ "@bitcoinerlab/secp256k1": "^1.1.1",
19
+ "@ethereumjs/common": "2.6.5",
20
+ "@ethereumjs/tx": "3.5.2",
21
+ "@metamask/eth-sig-util": "^7.0.0",
22
+ "@shapeshiftoss/hdwallet-core": "^1.62.4-gridplus.alpha.0",
23
+ "bech32": "^1.1.4",
24
+ "bs58": "^5.0.0",
25
+ "crypto-js": "^4.2.0",
26
+ "gridplus-sdk": "^3.2.0",
27
+ "lodash": "^4.17.21"
28
+ },
29
+ "devDependencies": {
30
+ "@types/crypto-js": "^4.2.2",
31
+ "typedoc": "^0.20.36"
32
+ },
33
+ "nohoist": [
34
+ "@ethereumjs/common",
35
+ "@ethereumjs/tx"
36
+ ],
37
+ "gitHead": "1f6350eeb399435826c5be82a39861334cfcedc2"
38
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@shapeshiftoss/hdwallet-gridplus",
3
+ "version": "1.62.4-alpha.214",
4
+ "license": "MIT",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "dist/index.js",
9
+ "source": "src/index.ts",
10
+ "types": "dist/index.d.ts",
11
+ "scripts": {
12
+ "build": "tsc --build",
13
+ "build:docs": "typedoc --out docs --target es6 --theme minimal --mode file src",
14
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
15
+ "prepublishOnly": "yarn clean && yarn build"
16
+ },
17
+ "dependencies": {
18
+ "@bitcoinerlab/secp256k1": "^1.1.1",
19
+ "@ethereumjs/common": "2.6.5",
20
+ "@ethereumjs/tx": "3.5.2",
21
+ "@metamask/eth-sig-util": "^7.0.0",
22
+ "@shapeshiftoss/hdwallet-core": "^1.62.4-alpha.214",
23
+ "bech32": "^1.1.4",
24
+ "bs58": "^5.0.0",
25
+ "crypto-js": "^4.2.0",
26
+ "gridplus-sdk": "^3.2.0",
27
+ "lodash": "^4.17.21"
28
+ },
29
+ "devDependencies": {
30
+ "@types/crypto-js": "^4.2.2",
31
+ "typedoc": "^0.20.36"
32
+ },
33
+ "nohoist": [
34
+ "@ethereumjs/common",
35
+ "@ethereumjs/tx"
36
+ ],
37
+ "gitHead": "53e4b5e3dff9cdeaf083ff306e4b896030bea9ad"
38
+ }
package/src/adapter.ts ADDED
@@ -0,0 +1,109 @@
1
+ import * as core from "@shapeshiftoss/hdwallet-core";
2
+
3
+ import { GridPlusHDWallet } from "./gridplus";
4
+ import { GridPlusTransport } from "./transport";
5
+
6
+ export class GridPlusAdapter {
7
+ keyring: core.Keyring;
8
+ private activeTransports: Map<string, GridPlusTransport> = new Map();
9
+
10
+ constructor(keyring: core.Keyring) {
11
+ this.keyring = keyring;
12
+ }
13
+
14
+ public static useKeyring(keyring: core.Keyring) {
15
+ return new GridPlusAdapter(keyring);
16
+ }
17
+
18
+ public async connectDevice(
19
+ deviceId: string,
20
+ password?: string,
21
+ existingSessionId?: string
22
+ ): Promise<{ transport: GridPlusTransport; isPaired: boolean; sessionId: string }> {
23
+ const transport = (() => {
24
+ const existing = this.activeTransports.get(deviceId);
25
+ if (existing) return existing;
26
+
27
+ const newTransport = new GridPlusTransport({
28
+ deviceId,
29
+ password: password || "shapeshift-default",
30
+ });
31
+ this.activeTransports.set(deviceId, newTransport);
32
+ return newTransport;
33
+ })();
34
+
35
+ const { isPaired, sessionId } = await transport.setup(deviceId, password, existingSessionId);
36
+ return { transport, isPaired, sessionId };
37
+ }
38
+
39
+ public async pairConnectedDevice(deviceId: string, pairingCode: string): Promise<GridPlusHDWallet> {
40
+ const transport = this.activeTransports.get(deviceId);
41
+ if (!transport) {
42
+ throw new Error("Device not connected. Call connectDevice first.");
43
+ }
44
+
45
+ try {
46
+ const pairingSuccess = await transport.pair(pairingCode);
47
+
48
+ if (!pairingSuccess) {
49
+ throw new Error("Pairing failed. Please check the 8-character code displayed on your Lattice device.");
50
+ }
51
+
52
+ const wallet = new GridPlusHDWallet(transport);
53
+ wallet.setActiveWalletId(deviceId);
54
+ await wallet.initialize();
55
+ this.keyring.add(wallet, deviceId);
56
+ this.activeTransports.delete(deviceId);
57
+
58
+ return wallet;
59
+ } catch (error) {
60
+ throw new Error(`GridPlus pairing failed: ${error instanceof Error ? error.message : "Unknown error"}`);
61
+ }
62
+ }
63
+
64
+ public async pairDevice(
65
+ deviceId: string,
66
+ password?: string,
67
+ pairingCode?: string,
68
+ existingSessionId?: string
69
+ ): Promise<GridPlusHDWallet> {
70
+ const existingWallet = this.keyring.get<GridPlusHDWallet>(deviceId);
71
+ if (existingWallet) {
72
+ // Reset Client activeWallets state and fetch fresh UIDs from currently inserted SafeCard
73
+ await existingWallet.transport.setup(deviceId, password, existingSessionId);
74
+ // Ensure the wallet has the correct active walletId set
75
+ existingWallet.setActiveWalletId(deviceId);
76
+ // Reinitialize to clear cached addresses when reconnecting (e.g., SafeCard swap)
77
+ await existingWallet.initialize();
78
+ return existingWallet;
79
+ }
80
+
81
+ const { isPaired } = await this.connectDevice(deviceId, password, existingSessionId);
82
+
83
+ if (!isPaired) {
84
+ if (pairingCode) {
85
+ return await this.pairConnectedDevice(deviceId, pairingCode);
86
+ } else {
87
+ throw new Error("PAIRING_REQUIRED");
88
+ }
89
+ }
90
+
91
+ // Already paired - create wallet directly
92
+ const transport = this.activeTransports.get(deviceId)!;
93
+ const wallet = new GridPlusHDWallet(transport);
94
+ wallet.setActiveWalletId(deviceId);
95
+ await wallet.initialize();
96
+ this.keyring.add(wallet, deviceId);
97
+ this.activeTransports.delete(deviceId);
98
+ return wallet;
99
+ }
100
+
101
+ public async initialize(deviceId: string, password?: string): Promise<number> {
102
+ await this.pairDevice(deviceId, password);
103
+ return Object.keys(this.keyring.wallets).length;
104
+ }
105
+
106
+ public get(deviceId: string): GridPlusHDWallet {
107
+ return core.mustBeDefined(this.keyring.get<GridPlusHDWallet>(deviceId));
108
+ }
109
+ }