@shapeshiftoss/hdwallet-phantom 1.62.28 → 1.62.30
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/dist/adapter.d.ts +2 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +3 -2
- package/dist/adapter.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/phantom.d.ts +22 -8
- package/dist/phantom.d.ts.map +1 -1
- package/dist/phantom.js +78 -15
- package/dist/phantom.js.map +1 -1
- package/dist/sui.d.ts +6 -0
- package/dist/sui.d.ts.map +1 -0
- package/dist/sui.js +52 -0
- package/dist/sui.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +4 -2
- package/src/index.ts +1 -0
- package/src/phantom.ts +87 -18
- package/src/sui.ts +44 -0
- package/src/types.ts +7 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/CHANGELOG.md +0 -11
- package/package.json.bak +0 -29
package/src/phantom.ts
CHANGED
|
@@ -8,18 +8,20 @@ import isObject from "lodash/isObject";
|
|
|
8
8
|
import * as btc from "./bitcoin";
|
|
9
9
|
import * as eth from "./ethereum";
|
|
10
10
|
import { solanaSendTx, solanaSignTx } from "./solana";
|
|
11
|
-
import
|
|
11
|
+
import * as sui from "./sui";
|
|
12
|
+
import { PhantomEvmProvider, PhantomSolanaProvider, PhantomSuiProvider, PhantomUtxoProvider } from "./types";
|
|
12
13
|
|
|
13
14
|
export function isPhantom(wallet: core.HDWallet): wallet is PhantomHDWallet {
|
|
14
15
|
return isObject(wallet) && (wallet as any)._isPhantom;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export class PhantomHDWalletInfo
|
|
18
|
-
implements core.HDWalletInfo, core.BTCWalletInfo, core.ETHWalletInfo, core.SolanaWalletInfo
|
|
19
|
+
implements core.HDWalletInfo, core.BTCWalletInfo, core.ETHWalletInfo, core.SolanaWalletInfo, core.SuiWalletInfo
|
|
19
20
|
{
|
|
20
21
|
readonly _supportsBTCInfo = true;
|
|
21
22
|
readonly _supportsETHInfo = true;
|
|
22
23
|
readonly _supportsSolanaInfo = true;
|
|
24
|
+
readonly _supportsSuiInfo = true;
|
|
23
25
|
|
|
24
26
|
evmProvider: PhantomEvmProvider;
|
|
25
27
|
|
|
@@ -169,47 +171,63 @@ export class PhantomHDWalletInfo
|
|
|
169
171
|
public solanaNextAccountPath(msg: core.SolanaAccountPath): core.SolanaAccountPath | undefined {
|
|
170
172
|
throw new Error("Method not implemented");
|
|
171
173
|
}
|
|
174
|
+
|
|
175
|
+
/** Sui */
|
|
176
|
+
|
|
177
|
+
public suiGetAccountPaths(msg: core.SuiGetAccountPaths): Array<core.SuiAccountPath> {
|
|
178
|
+
return core.suiGetAccountPaths(msg);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
182
|
+
public suiNextAccountPath(msg: core.SuiAccountPath): core.SuiAccountPath | undefined {
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
172
185
|
}
|
|
173
186
|
|
|
174
187
|
export class PhantomHDWallet
|
|
175
188
|
extends PhantomHDWalletInfo
|
|
176
|
-
implements core.HDWallet, core.BTCWallet, core.ETHWallet, core.SolanaWallet
|
|
189
|
+
implements core.HDWallet, core.BTCWallet, core.ETHWallet, core.SolanaWallet, core.SuiWallet
|
|
177
190
|
{
|
|
178
191
|
readonly _supportsBTC = true;
|
|
179
192
|
readonly _supportsETH = true;
|
|
180
|
-
readonly _supportsEthSwitchChain =
|
|
193
|
+
readonly _supportsEthSwitchChain = true;
|
|
181
194
|
readonly _supportsAvalanche = false;
|
|
182
195
|
readonly _supportsOptimism = false;
|
|
183
|
-
|
|
184
|
-
// https://github.com/orgs/phantom/discussions/294
|
|
185
|
-
readonly _supportsPolygon = false;
|
|
196
|
+
readonly _supportsPolygon = true;
|
|
186
197
|
readonly _supportsGnosis = false;
|
|
187
198
|
readonly _supportsArbitrum = false;
|
|
188
199
|
readonly _supportsArbitrumNova = false;
|
|
189
200
|
readonly _supportsBase = true;
|
|
190
|
-
readonly _supportsMonad =
|
|
201
|
+
readonly _supportsMonad = true;
|
|
191
202
|
readonly _supportsPlasma = false;
|
|
192
|
-
readonly _supportsHyperEvm =
|
|
203
|
+
readonly _supportsHyperEvm = true;
|
|
193
204
|
readonly _supportsBSC = false;
|
|
194
205
|
readonly _supportsSolana = true;
|
|
206
|
+
readonly _supportsSui = true;
|
|
195
207
|
readonly _isPhantom = true;
|
|
196
208
|
|
|
197
209
|
evmProvider: PhantomEvmProvider;
|
|
198
210
|
bitcoinProvider: PhantomUtxoProvider;
|
|
199
211
|
solanaProvider: PhantomSolanaProvider;
|
|
212
|
+
suiProvider?: PhantomSuiProvider;
|
|
200
213
|
|
|
201
214
|
ethAddress?: Address | null;
|
|
215
|
+
btcAddress?: string | null;
|
|
216
|
+
solanaAddress?: string | null;
|
|
217
|
+
suiAddress?: string | null;
|
|
202
218
|
|
|
203
219
|
constructor(
|
|
204
220
|
evmProvider: PhantomEvmProvider,
|
|
205
221
|
bitcoinProvider: PhantomUtxoProvider,
|
|
206
|
-
solanaProvider: PhantomSolanaProvider
|
|
222
|
+
solanaProvider: PhantomSolanaProvider,
|
|
223
|
+
suiProvider?: PhantomSuiProvider
|
|
207
224
|
) {
|
|
208
225
|
super(evmProvider);
|
|
209
226
|
|
|
210
227
|
this.evmProvider = evmProvider;
|
|
211
228
|
this.bitcoinProvider = bitcoinProvider;
|
|
212
229
|
this.solanaProvider = solanaProvider;
|
|
230
|
+
this.suiProvider = suiProvider;
|
|
213
231
|
}
|
|
214
232
|
|
|
215
233
|
public async getDeviceID(): Promise<string> {
|
|
@@ -297,19 +315,17 @@ export class PhantomHDWallet
|
|
|
297
315
|
|
|
298
316
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
299
317
|
public async ethGetAddress(_msg: core.ETHGetAddress): Promise<core.Address | null> {
|
|
300
|
-
if (this.ethAddress)
|
|
301
|
-
return this.ethAddress;
|
|
302
|
-
}
|
|
318
|
+
if (this.ethAddress) return this.ethAddress;
|
|
303
319
|
|
|
304
320
|
const address = await eth.ethGetAddress(this.evmProvider);
|
|
305
321
|
|
|
306
322
|
if (address) {
|
|
307
323
|
this.ethAddress = address;
|
|
308
324
|
return address;
|
|
309
|
-
} else {
|
|
310
|
-
this.ethAddress = null;
|
|
311
|
-
return null;
|
|
312
325
|
}
|
|
326
|
+
|
|
327
|
+
this.ethAddress = null;
|
|
328
|
+
return null;
|
|
313
329
|
}
|
|
314
330
|
|
|
315
331
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -339,9 +355,34 @@ export class PhantomHDWallet
|
|
|
339
355
|
return recoverAddress(digest, msg.signature) === msg.address;
|
|
340
356
|
}
|
|
341
357
|
|
|
358
|
+
public async ethGetChainId(): Promise<number | null> {
|
|
359
|
+
try {
|
|
360
|
+
const chainIdHex = await this.evmProvider.request({ method: "eth_chainId" });
|
|
361
|
+
return parseInt(chainIdHex, 16);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
console.error("Failed to get chain ID from Phantom:", error);
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
public async ethSwitchChain(params: core.AddEthereumChainParameter): Promise<void> {
|
|
369
|
+
const parsedChainId = parseInt(params.chainId, 16);
|
|
370
|
+
const currentChainId = await this.ethGetChainId();
|
|
371
|
+
|
|
372
|
+
if (currentChainId === parsedChainId) return;
|
|
373
|
+
|
|
374
|
+
await this.evmProvider.request({
|
|
375
|
+
method: "wallet_switchEthereumChain",
|
|
376
|
+
params: [{ chainId: params.chainId }],
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
342
380
|
/** Bitcoin */
|
|
343
381
|
|
|
344
382
|
public async btcGetAddress(msg: core.BTCGetAddress): Promise<string | null> {
|
|
383
|
+
// Use cached address if available to prevent rate limiting
|
|
384
|
+
if (this.btcAddress !== undefined) return this.btcAddress;
|
|
385
|
+
|
|
345
386
|
const value = await (async () => {
|
|
346
387
|
switch (msg.coin) {
|
|
347
388
|
case "Bitcoin": {
|
|
@@ -354,8 +395,12 @@ export class PhantomHDWallet
|
|
|
354
395
|
return null;
|
|
355
396
|
}
|
|
356
397
|
})();
|
|
357
|
-
if (!value || typeof value !== "string")
|
|
398
|
+
if (!value || typeof value !== "string") {
|
|
399
|
+
this.btcAddress = null;
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
358
402
|
|
|
403
|
+
this.btcAddress = value;
|
|
359
404
|
return value;
|
|
360
405
|
}
|
|
361
406
|
|
|
@@ -393,8 +438,13 @@ export class PhantomHDWallet
|
|
|
393
438
|
/** Solana */
|
|
394
439
|
|
|
395
440
|
public async solanaGetAddress(): Promise<string | null> {
|
|
441
|
+
// Use cached address if available to prevent rate limiting
|
|
442
|
+
if (this.solanaAddress !== undefined) return this.solanaAddress;
|
|
443
|
+
|
|
396
444
|
const { publicKey } = await this.solanaProvider.connect();
|
|
397
|
-
|
|
445
|
+
const address = publicKey.toString();
|
|
446
|
+
this.solanaAddress = address;
|
|
447
|
+
return address;
|
|
398
448
|
}
|
|
399
449
|
|
|
400
450
|
public async solanaSignTx(msg: core.SolanaSignTx): Promise<core.SolanaSignedTx | null> {
|
|
@@ -406,4 +456,23 @@ export class PhantomHDWallet
|
|
|
406
456
|
const address = await this.solanaGetAddress();
|
|
407
457
|
return address ? solanaSendTx(msg, this.solanaProvider, address) : null;
|
|
408
458
|
}
|
|
459
|
+
|
|
460
|
+
/** Sui */
|
|
461
|
+
|
|
462
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
463
|
+
public async suiGetAddress(_msg: core.SuiGetAddress): Promise<string | null> {
|
|
464
|
+
if (!this.suiProvider) return null;
|
|
465
|
+
|
|
466
|
+
// Use cached address if available to prevent rate limiting
|
|
467
|
+
if (this.suiAddress !== undefined) return this.suiAddress;
|
|
468
|
+
|
|
469
|
+
const address = await sui.suiGetAddress(this.suiProvider);
|
|
470
|
+
this.suiAddress = address;
|
|
471
|
+
return address;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
public async suiSignTx(msg: core.SuiSignTx): Promise<core.SuiSignedTx | null> {
|
|
475
|
+
if (!this.suiProvider) return null;
|
|
476
|
+
return sui.suiSignTx(msg, this.suiProvider);
|
|
477
|
+
}
|
|
409
478
|
}
|
package/src/sui.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as core from "@shapeshiftoss/hdwallet-core";
|
|
2
|
+
|
|
3
|
+
import { PhantomSuiProvider } from "./types";
|
|
4
|
+
|
|
5
|
+
export async function suiGetAddress(provider: PhantomSuiProvider): Promise<string | null> {
|
|
6
|
+
const account = await provider.requestAccount();
|
|
7
|
+
|
|
8
|
+
if (account && account.address) return account.address;
|
|
9
|
+
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function suiSignTx(msg: core.SuiSignTx, provider: PhantomSuiProvider): Promise<core.SuiSignedTx | null> {
|
|
14
|
+
const account = await provider.requestAccount();
|
|
15
|
+
|
|
16
|
+
const result = await provider.signTransaction({
|
|
17
|
+
transaction: msg.transactionJson,
|
|
18
|
+
address: account.address,
|
|
19
|
+
networkID: "sui:mainnet",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const fullSignatureBuffer = Buffer.from(result.signature, "base64");
|
|
23
|
+
|
|
24
|
+
// Phantom returns a 97-byte signature: 1 byte flag + 64 bytes signature + 32 bytes public key
|
|
25
|
+
if (fullSignatureBuffer.length !== 97) {
|
|
26
|
+
throw new Error(`Unexpected signature length: ${fullSignatureBuffer.length} bytes (expected 97)`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const signatureBytes = fullSignatureBuffer.slice(1, 65);
|
|
30
|
+
const publicKeyBytes = fullSignatureBuffer.slice(65, 97);
|
|
31
|
+
|
|
32
|
+
const signatureHex = signatureBytes.toString("hex");
|
|
33
|
+
const publicKeyHex = publicKeyBytes.toString("hex");
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
signature: signatureHex,
|
|
37
|
+
publicKey: publicKeyHex,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function suiSignMessage(message: Uint8Array, provider: PhantomSuiProvider): Promise<string | null> {
|
|
42
|
+
const result = await provider.signMessage(message);
|
|
43
|
+
return result.signature;
|
|
44
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type PhantomEvmProvider = providers.ExternalProvider & {
|
|
|
8
8
|
_metamask: {
|
|
9
9
|
isUnlocked: () => boolean;
|
|
10
10
|
};
|
|
11
|
+
request: (args: { method: string; params?: unknown[] | object }) => Promise<unknown>;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
export type PhantomUtxoProvider = providers.ExternalProvider & {
|
|
@@ -30,3 +31,9 @@ export type PhantomSolanaProvider = providers.ExternalProvider & {
|
|
|
30
31
|
signTransaction(transaction: VersionedTransaction): Promise<VersionedTransaction>;
|
|
31
32
|
signAndSendTransaction(transaction: VersionedTransaction): Promise<{ signature: TransactionSignature }>;
|
|
32
33
|
};
|
|
34
|
+
|
|
35
|
+
export type PhantomSuiProvider = {
|
|
36
|
+
requestAccount(): Promise<{ address: string; publicKey: Uint8Array }>;
|
|
37
|
+
signMessage(message: Uint8Array, encoding?: string): Promise<{ signature: string }>;
|
|
38
|
+
signTransaction(params: { transaction: string; address: string; networkID: string }): Promise<{ signature: string }>;
|
|
39
|
+
};
|