-
Notifications
You must be signed in to change notification settings - Fork 90
feat: seeker wallet solana support #786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
8237573
15a6661
49ef9c2
2c07219
938e0b0
c278723
13750f4
5d55319
aebfb2c
c1d4f61
83b24b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "name": "@shapeshiftoss/hdwallet-seeker", | ||
| "version": "1.62.41", | ||
| "license": "MIT", | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "main": "dist/index.js", | ||
| "source": "src/index.ts", | ||
| "types": "dist/index.d.ts", | ||
| "files": [ | ||
| "dist" | ||
| ], | ||
| "scripts": { | ||
| "build": "tsc --build", | ||
| "clean": "rm -rf dist tsconfig.tsbuildinfo", | ||
| "prepublishOnly": "yarn clean && yarn build" | ||
| }, | ||
| "dependencies": { | ||
| "@shapeshiftoss/hdwallet-core": "^1.62.41", | ||
| "@solana/web3.js": "^1.95.8" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,210 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BIP32Path, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DescribePath, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GetPublicKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HDWallet, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PathDescription, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ping, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Pong, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PublicKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SolanaAccountPath, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SolanaGetAccountPaths, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SolanaGetAddress, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SolanaSignedTx, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SolanaSignTx, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SolanaTxSignature, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from '@shapeshiftoss/hdwallet-core' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { solanaBuildTransaction } from '@shapeshiftoss/hdwallet-core' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { SeekerMessageHandler } from './types' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class SeekerHDWallet implements HDWallet { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private deviceId: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private pubkey: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private messageHandler: SeekerMessageHandler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| readonly _supportsSolana = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| readonly _supportsSolanaInfo = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constructor(deviceId: string, pubkey: string, messageHandler: SeekerMessageHandler) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.deviceId = deviceId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.pubkey = pubkey | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.messageHandler = messageHandler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getVendor(): string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 'Seeker' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasOnDevicePinEntry(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasOnDevicePassphrase(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasOnDeviceDisplay(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasOnDeviceRecovery(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hasNativeShapeShift(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supportsBip44Accounts(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supportsOfflineSigning(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supportsBroadcast(): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| describePath(_msg: DescribePath): PathDescription { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isKnown: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| verbose: 'Seeker Solana', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| coin: 'Solana', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getDeviceID(): Promise<string> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve(this.deviceId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getFeatures(): Promise<Record<string, unknown>> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vendor: 'Seeker', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model: 'Seeker', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: 'Seeker Wallet', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getFirmwareVersion(): Promise<string> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve('1.0.0') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getModel(): Promise<string> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve('Seeker') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getLabel(): Promise<string> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve('Seeker Wallet') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getPublicKeys(_msg: GetPublicKey[]): Promise<(PublicKey | null)[] | null> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve([{ xpub: this.pubkey }]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isInitialized(): Promise<boolean> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isLocked(): Promise<boolean> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve(false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clearSession(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialize(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ping(_msg: Ping): Promise<Pong> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve({ msg: 'pong' }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sendPin(_pin: string): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sendPassphrase(_passphrase: string): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sendCharacter(_character: string): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sendWord(_word: string): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cancel(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| wipe(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reset(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| recover(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loadDevice(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| disconnect(): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getAddress(): string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return this.pubkey | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solanaGetAddress(_msg: SolanaGetAddress): Promise<string | null> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Promise.resolve(this.pubkey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solanaGetAccountPaths(_msg: SolanaGetAccountPaths): SolanaAccountPath[] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const SOLANA_BIP44_PATH: BIP32Path = [0x80000000 + 44, 0x80000000 + 501, 0x80000000 + 0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [{ addressNList: SOLANA_BIP44_PATH }] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solanaNextAccountPath(_msg: SolanaAccountPath): SolanaAccountPath | undefined { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async solanaSignTx(msg: SolanaSignTx): Promise<SolanaSignedTx | null> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const transaction = solanaBuildTransaction(msg, this.pubkey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const serializedTx = Buffer.from(transaction.serialize()).toString('base64') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const result = await this.messageHandler.signTransaction(serializedTx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!result.success || !result.signedTransaction) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(result.error ?? 'Failed to sign transaction') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| serialized: result.signedTransaction, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| signatures: [result.signedTransaction], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+184
to
+196
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Find SolanaSignedTx definition and examine its structure
rg -n "interface SolanaSignedTx|type SolanaSignedTx|class SolanaSignedTx" packages -g '*.ts' -A 5Repository: shapeshift/hdwallet Length of output: 45 🏁 Script executed: # Find all solanaSignTx implementations
rg -n "solanaSignTx" packages -g '*.ts' -B 2 -A 15Repository: shapeshift/hdwallet Length of output: 45 🏁 Script executed: # Check SolanaSignTx and related types in hdwallet-core
fd -e ts packages/hdwallet-core | head -20Repository: shapeshift/hdwallet Length of output: 456 🏁 Script executed: # List available packages
ls -la packages/ | head -20Repository: shapeshift/hdwallet Length of output: 1368 🏁 Script executed: # Search for SolanaSignedTx definition
rg "SolanaSignedTx" packages --type ts -B 2 -A 5Repository: shapeshift/hdwallet Length of output: 45 🏁 Script executed: # Search for solanaSignTx method implementations
rg "solanaSignTx\s*\(" packages --type ts -B 1 -A 15Repository: shapeshift/hdwallet Length of output: 45 🏁 Script executed: # Continue listing packages
ls -la packages/ | tail -10Repository: shapeshift/hdwallet Length of output: 745 🏁 Script executed: # Search for SolanaSignedTx without context flags
rg "SolanaSignedTx" packagesRepository: shapeshift/hdwallet Length of output: 45 🏁 Script executed: # Look for seeker package
ls -la packages/ | grep seekerRepository: shapeshift/hdwallet Length of output: 127 🏁 Script executed: # Search for Solana-related types more broadly
rg "Solana" packages --type ts | grep -i "interface\|type\|class" | head -20Repository: shapeshift/hdwallet Length of output: 45 🏁 Script executed: # Look at the seeker adapter file mentioned in the review
cat packages/hdwallet-seeker/src/adapter.ts | head -220 | tail -50Repository: shapeshift/hdwallet Length of output: 1659 🏁 Script executed: # Check hdwallet-core for Solana types
find packages/hdwallet-core -name "*.ts" | xargs grep -l "Solana" | head -5Repository: shapeshift/hdwallet Length of output: 172 🏁 Script executed: # Check SolanaSignedTx type definition in hdwallet-core
cat packages/hdwallet-core/src/solana.ts | head -150Repository: shapeshift/hdwallet Length of output: 4945 🏁 Script executed: # Look for other solanaSignTx implementations
find packages -name "*.ts" -exec grep -l "solanaSignTx" {} \;Repository: shapeshift/hdwallet Length of output: 583 🏁 Script executed: # Check if there are any other Solana adapter implementations
ls -la packages/hdwallet-*/src/ | grep -i solanaRepository: shapeshift/hdwallet Length of output: 482 🏁 Script executed: # Check phantom solanaSignTx implementation
cat packages/hdwallet-phantom/src/solana.tsRepository: shapeshift/hdwallet Length of output: 1096 🏁 Script executed: # Check ledger solanaSignTx implementation
cat packages/hdwallet-ledger/src/solana.tsRepository: shapeshift/hdwallet Length of output: 1876 🏁 Script executed: # Check native solanaSignTx implementation
cat packages/hdwallet-native/src/solana.tsRepository: shapeshift/hdwallet Length of output: 2589 🏁 Script executed: # Check gridplus solanaSignTx implementation
cat packages/hdwallet-gridplus/src/solana.tsRepository: shapeshift/hdwallet Length of output: 1977 🏁 Script executed: # Check trezor solanaSignTx implementation
cat packages/hdwallet-trezor/src/solana.tsRepository: shapeshift/hdwallet Length of output: 2918
The current code returns Deserialize the signed transaction and extract its signatures: Suggested fix+import { Transaction } from '@solana/web3.js'
async solanaSignTx(msg: SolanaSignTx): Promise<SolanaSignedTx | null> {
const transaction = solanaBuildTransaction(msg, this.pubkey)
const serializedTx = Buffer.from(transaction.serialize()).toString('base64')
const result = await this.messageHandler.signTransaction(serializedTx)
if (!result.success || !result.signedTransaction) {
throw new Error(result.error ?? 'Failed to sign transaction')
}
+ const signedTx = Transaction.from(Buffer.from(result.signedTransaction, 'base64'))
+ const signatures = signedTx.signatures
+ .map(s => (s.signature ? Buffer.from(s.signature).toString('base64') : null))
+ .filter((s): s is string => Boolean(s))
+
return {
serialized: result.signedTransaction,
- signatures: [result.signedTransaction],
+ signatures,
}
}📝 Committable suggestion
Suggested change
🧰 Tools🪛 ESLint[error] 185-185: Insert (prettier/prettier) [error] 186-186: Replace (prettier/prettier) [error] 188-188: Insert (prettier/prettier) [error] 190-190: Replace (prettier/prettier) [error] 196-196: Insert (prettier/prettier) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async solanaSendTx(msg: SolanaSignTx): Promise<SolanaTxSignature | null> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const transaction = solanaBuildTransaction(msg, this.pubkey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const serializedTx = Buffer.from(transaction.serialize()).toString('base64') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const result = await this.messageHandler.signAndSendTransaction(serializedTx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!result.success || !result.signature) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(result.error ?? 'Failed to sign and send transaction') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { signature: result.signature } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| export { SeekerHDWallet } from './adapter' | ||
| export type { | ||
| SeekerMessageHandler, | ||
| SeekerAvailabilityResult, | ||
| SeekerAuthResult, | ||
| SeekerAddressResult, | ||
| SeekerStatusResult, | ||
| SeekerSignResult, | ||
| SeekerSendResult, | ||
| SeekerAppIdentity, | ||
| SeekerConfig, | ||
| } from './types' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| export type SeekerAvailabilityResult = { | ||
| available: boolean | ||
| } | ||
|
|
||
| export type SeekerAuthResult = { | ||
| success: boolean | ||
| address?: string | ||
| label?: string | ||
| error?: string | ||
| } | ||
|
|
||
| export type SeekerAddressResult = { | ||
| address: string | null | ||
| } | ||
|
|
||
| export type SeekerStatusResult = { | ||
| available: boolean | ||
| isAuthorized: boolean | ||
| address: string | null | ||
| } | ||
|
|
||
| export type SeekerSignResult = { | ||
| success: boolean | ||
| signedTransaction?: string | ||
| error?: string | ||
| } | ||
|
|
||
| export type SeekerSendResult = { | ||
| success: boolean | ||
| signature?: string | ||
| error?: string | ||
| } | ||
|
|
||
| export interface SeekerMessageHandler { | ||
| checkAvailability(): Promise<SeekerAvailabilityResult> | ||
| authorize(cluster?: 'mainnet-beta' | 'devnet' | 'testnet'): Promise<SeekerAuthResult> | ||
| deauthorize(): Promise<{ success: boolean; error?: string }> | ||
| getAddress(): Promise<SeekerAddressResult> | ||
| getStatus(): Promise<SeekerStatusResult> | ||
| signTransaction(transaction: string): Promise<SeekerSignResult> | ||
| signAndSendTransaction(transaction: string): Promise<SeekerSendResult> | ||
| } | ||
|
|
||
| export interface SeekerAppIdentity { | ||
| name: string | ||
| uri: string | ||
| icon: string | ||
| } | ||
|
|
||
| export interface SeekerConfig { | ||
| appIdentity: SeekerAppIdentity | ||
| cluster?: 'mainnet-beta' | 'devnet' | 'testnet' | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "extends": "../../tsconfig.json", | ||
| "compilerOptions": { | ||
| "rootDir": "src", | ||
| "outDir": "dist" | ||
| }, | ||
| "include": ["src/**/*"], | ||
| "exclude": ["node_modules", "dist", "**/*.test.ts"], | ||
| "references": [{ "path": "../hdwallet-core" }] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align
getPublicKeysoutput length with the request.Line 103 returns a single element regardless of input size, which can break callers expecting one result per request. Either validate single-key usage or map to the input length.
✅ Suggested fix (mirror input length)
📝 Committable suggestion
🧰 Tools
🪛 ESLint
[error] 103-103: '_msg' is defined but never used.
(
@typescript-eslint/no-unused-vars)[error] 104-104: Insert
;(prettier/prettier)
🤖 Prompt for AI Agents