-
Notifications
You must be signed in to change notification settings - Fork 89
feat: implement starknet for native #774
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
Merged
Merged
Changes from 43 commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
6a2302a
chore: version packages to 1.62.32-starknet.0
NeOMakinG dca2f76
fix: cleanup shit
gomesalexandre 1917f29
fix: restore starknet dependencies to hdwallet-native
gomesalexandre 6c6b329
chore: version packages to 1.62.33-starknet.0
gomesalexandre 45b0493
fix: ci
gomesalexandre deb8f8e
[skip ci] wip: skip ci
gomesalexandre 87270a8
fix: ci
gomesalexandre a2ce8d8
chore: version packages to 1.62.33-starknet.1
gomesalexandre 9522d96
fix: sig length
gomesalexandre d2979c0
feat: don't pollute bip32 node
gomesalexandre 43949d3
chore: version packages to 1.62.33-starknet.2
gomesalexandre 601c369
feat: add comprehensive logging for starknet debugging
gomesalexandre 95aff1c
chore: version packages to 1.62.33-starknet.3
gomesalexandre 754eee5
fix: make starkMasterKey optional in initialize
gomesalexandre 9b8ee2b
chore: version packages to 1.62.33-starknet.4
gomesalexandre 41c6e7a
feat: add initialization logging
gomesalexandre 1a84c9b
chore: version packages to 1.62.33-starknet.5
gomesalexandre e71eaa3
fix: stark master key initialization in constructor
gomesalexandre 63b360d
chore: version packages to 1.62.33-starknet.6
gomesalexandre cd03b76
chore: version packages to 1.62.33-starknet.6
gomesalexandre 2d43148
fix: add stark master key to loadDevice
gomesalexandre 81966c7
chore: version packages to 1.62.33-starknet.8
gomesalexandre 1a2fc8c
fix: support non-hardened derivation in stark engine
gomesalexandre 6f8d24e
chore: version packages to 1.62.33-starknet.9
gomesalexandre ae0cfa5
fix: compute actual contract address instead of returning public key
gomesalexandre e3d0a98
chore: version packages to 1.62.33-starknet.10
gomesalexandre dce57a5
docs: add STARK curve and Starknet spec references
gomesalexandre 746cf06
docs: add comprehensive Stark curve documentation and references
gomesalexandre 48b924f
docs: add comments explaining Stark master key in bip32, dummy, and a…
gomesalexandre bac3fa7
refactor: clean up debugging logs and move stark init back to Promise…
gomesalexandre fb79a67
fix: pad Starknet public keys to 64 hex chars
gomesalexandre ef327d7
chore: version packages to 1.62.33-starknet.11
gomesalexandre 6b84173
fix: pad contract address to 64 hex chars
gomesalexandre b44b240
chore: version packages to 1.62.33-starknet.12
gomesalexandre 4dc33a9
chore: remove debug logging
gomesalexandre 11f947d
chore: version packages to 1.62.33-starknet.13
gomesalexandre 7be85cb
chore: version packages to 1.62.33-starknet.14
gomesalexandre 8feaab6
chore: revert versions to 1.62.32 and use npmjs registry
gomesalexandre bf77265
fix: remove carets from 1.62.32 versions (should be exact)
gomesalexandre 2a80641
chore: pin all dependency versions across all packages
gomesalexandre cfb2b6a
feat: clean shit up
gomesalexandre ffafa43
fix: uh oh
gomesalexandre c1b54f1
fix: add starkMasterKey to native wallet tests
gomesalexandre 2b1c409
style: format loadDevice calls in native tests
gomesalexandre 2c1b669
chore(release): publish 1.62.33
gomesalexandre File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import { addressNListToBIP32, slip44ByCoin } from "./utils"; | ||
| import { BIP32Path, HDWallet, HDWalletInfo, PathDescription } from "./wallet"; | ||
|
|
||
| export interface StarknetGetAddress { | ||
| addressNList: BIP32Path; | ||
| showDisplay?: boolean; | ||
| } | ||
|
|
||
| export interface StarknetGetPublicKey { | ||
| addressNList: BIP32Path; | ||
| } | ||
|
|
||
| export interface StarknetSignTx { | ||
| addressNList: BIP32Path; | ||
| txHash: string; | ||
| } | ||
|
|
||
| export interface StarknetSignedTx { | ||
| signature: string[]; | ||
| } | ||
|
|
||
| export interface StarknetGetAccountPaths { | ||
| accountIdx: number; | ||
| } | ||
|
|
||
| export interface StarknetAccountPath { | ||
| addressNList: BIP32Path; | ||
| } | ||
|
|
||
| export interface StarknetWalletInfo extends HDWalletInfo { | ||
| readonly _supportsStarknetInfo: boolean; | ||
|
|
||
| starknetGetAccountPaths(msg: StarknetGetAccountPaths): Array<StarknetAccountPath>; | ||
| starknetNextAccountPath(msg: StarknetAccountPath): StarknetAccountPath | undefined; | ||
| } | ||
|
|
||
| export interface StarknetWallet extends StarknetWalletInfo, HDWallet { | ||
| readonly _supportsStarknet: boolean; | ||
|
|
||
| starknetGetAddress(msg: StarknetGetAddress): Promise<string | null>; | ||
| starknetGetPublicKey(msg: StarknetGetPublicKey): Promise<string | null>; | ||
| starknetSignTx(msg: StarknetSignTx): Promise<StarknetSignedTx | null>; | ||
| } | ||
|
|
||
| export function starknetDescribePath(path: BIP32Path): PathDescription { | ||
| const pathStr = addressNListToBIP32(path); | ||
| const unknown: PathDescription = { | ||
| verbose: pathStr, | ||
| coin: "Starknet", | ||
| isKnown: false, | ||
| }; | ||
|
|
||
| if (path.length != 5) return unknown; | ||
| if (path[0] != 0x80000000 + 44) return unknown; | ||
| if (path[1] != 0x80000000 + slip44ByCoin("Starknet")) return unknown; | ||
| if ((path[2] & 0x80000000) >>> 0 !== 0x80000000) return unknown; | ||
| if (path[3] !== 0) return unknown; | ||
| if (path[4] !== 0) return unknown; | ||
|
|
||
| const index = path[2] & 0x7fffffff; | ||
| return { | ||
| verbose: `Starknet Account #${index}`, | ||
| accountIdx: index, | ||
| wholeAccount: true, | ||
| coin: "Starknet", | ||
| isKnown: true, | ||
| }; | ||
| } | ||
|
|
||
| export function starknetGetAccountPaths(msg: StarknetGetAccountPaths): Array<StarknetAccountPath> { | ||
| const slip44 = slip44ByCoin("Starknet"); | ||
| return [{ addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0] }]; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
packages/hdwallet-native/src/crypto/isolation/adapters/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,12 @@ | ||
| export { default as Bitcoin } from "./bitcoin"; | ||
| export { default as BIP32 } from "./bip32"; | ||
| export { default as Ed25519 } from "./ed25519"; | ||
| export { default as Stark } from "./stark"; | ||
| export { default as Ethereum } from "./ethereum"; | ||
| export { default as Binance } from "./binance"; | ||
| export { default as Cosmos } from "./cosmos"; | ||
| export { default as CosmosDirect } from "./cosmosDirect"; | ||
| export { default as Solana } from "./solana"; | ||
| export { default as Tron } from "./tron"; | ||
| export { default as Starknet } from "./starknet"; | ||
| export { default as Sui } from "./sui"; | ||
| export { default as Tron } from "./tron"; |
43 changes: 43 additions & 0 deletions
43
packages/hdwallet-native/src/crypto/isolation/adapters/stark.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import { Stark } from "../core"; | ||
|
|
||
| /** | ||
| * Stark curve adapter for Starknet | ||
| * | ||
| * Simple wrapper around Stark.Node providing derivation utilities. | ||
| * The Stark Node handles all Starknet-specific operations (key grinding, | ||
| * STARK curve public keys, and ECDSA signing on STARK curve). | ||
| * | ||
| * STARK Curve Specifications: | ||
| * - Curve type: Weierstrass (y² = x³ + ax + b) | ||
| * - Prime field (p): 2^251 + 17×2^192 + 1 (251-bit) | ||
| * - Curve parameters: a = 1, b = π (3141592...) | ||
| * - Curve order (n): 252-bit | ||
| * | ||
| * References: | ||
| * - STARK Curve Spec: https://docs.starkware.co/starkex/crypto/stark-curve.html | ||
| * - Key Derivation: https://docs.starkware.co/starkex/crypto/key-derivation.html | ||
| * - Account Standard: https://community.starknet.io/t/account-keys-and-addresses-derivation-standard/1230 | ||
| * - Starknet Cryptography: https://docs.starknet.io/architecture/cryptography/ | ||
| * - @scure/starknet: https://github.com/paulmillr/scure-starknet | ||
| */ | ||
| export class StarkAdapter { | ||
| readonly node: Stark.Node; | ||
|
|
||
| constructor(node: Stark.Node) { | ||
| this.node = node; | ||
| } | ||
|
|
||
| async getPublicKey(): Promise<string> { | ||
| return this.node.getPublicKey(); | ||
| } | ||
|
|
||
| async derive(index: number): Promise<this> { | ||
| return new StarkAdapter(await this.node.derive(index)) as this; | ||
| } | ||
|
|
||
| async derivePath(path: string): Promise<StarkAdapter> { | ||
| return Stark.derivePath<StarkAdapter>(this, path); | ||
| } | ||
| } | ||
|
|
||
| export default StarkAdapter; |
92 changes: 92 additions & 0 deletions
92
packages/hdwallet-native/src/crypto/isolation/adapters/starknet.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| import * as core from "@shapeshiftoss/hdwallet-core"; | ||
| import { CallData, hash } from "starknet"; | ||
|
|
||
| import { Isolation } from "../.."; | ||
|
|
||
| /** | ||
| * Starknet adapter using Stark curve engine | ||
| * | ||
| * Uses dedicated Stark engine with STARK curve operations instead of | ||
| * polluting the generic BIP32 secp256k1 engine with chain-specific code. | ||
| * | ||
| * ACCOUNT ABSTRACTION: | ||
| * All Starknet accounts are smart contracts (no EOAs). The account address is computed from: | ||
| * - Account contract class hash (OpenZeppelin, Argent, Braavos implementations) | ||
| * - Constructor calldata (including public key) | ||
| * - Salt (typically the public key) | ||
| * - Deployer address (0 for counterfactual deployment) | ||
| * | ||
| * DERIVATION PATH: | ||
| * Uses BIP-44 format: m/44'/9004'/accountIdx'/0/0 | ||
| * - SLIP-044 coin type: 9004 (Starknet) | ||
| * - Community consensus: BIP-44 preferred over EIP-2645 | ||
| * - See: https://community.starknet.io/t/account-keys-and-addresses-derivation-standard/1230 | ||
| * | ||
| * REFERENCES: | ||
| * - Starknet Account Architecture: https://docs.starknet.io/architecture/accounts/ | ||
| * - Account Abstraction Part I: https://medium.com/starknet-edu/account-abstraction-on-starknet-part-i-2ff84c6a3c30 | ||
| * - Account Abstraction Part II: https://medium.com/starknet-edu/account-abstraction-on-starknet-part-ii-24d52874e0bd | ||
| * - Account Creation Guide: https://starknetjs.com/docs/guides/create_account/ | ||
| * - OpenZeppelin Accounts: https://docs.openzeppelin.com/contracts-cairo/0.14.0/accounts | ||
| * - SLIP-044 Registry: https://github.com/satoshilabs/slips/blob/master/slip-0044.md | ||
| */ | ||
| export class StarknetAdapter { | ||
| protected readonly nodeAdapter: Isolation.Adapters.Stark; | ||
|
|
||
| // OpenZeppelin account v0.15.0-rc.0 class hash (used by most wallets) | ||
| // See: https://docs.openzeppelin.com/contracts-cairo/0.14.0/accounts | ||
| private readonly OZ_ACCOUNT_CLASS_HASH = "0x05b4b537eaa2399e3aa99c4e2e0208ebd6c71bc1467938cd52c798c601e43564"; | ||
|
|
||
| constructor(nodeAdapter: Isolation.Adapters.Stark) { | ||
| this.nodeAdapter = nodeAdapter; | ||
| } | ||
|
|
||
| /** | ||
| * Get Starknet public key from BIP32 path | ||
| */ | ||
| async getPublicKey(addressNList: core.BIP32Path): Promise<string> { | ||
| const bip32Path = core.addressNListToBIP32(addressNList); | ||
| const nodeAdapter = await this.nodeAdapter.derivePath(bip32Path); | ||
| const publicKey = await nodeAdapter.getPublicKey(); | ||
| return publicKey; | ||
| } | ||
|
|
||
| /** | ||
| * Get Starknet address from BIP32 path | ||
| * Computes the counterfactual contract address using OpenZeppelin account implementation | ||
| */ | ||
| async getAddress(addressNList: core.BIP32Path): Promise<string> { | ||
| const bip32Path = core.addressNListToBIP32(addressNList); | ||
| const nodeAdapter = await this.nodeAdapter.derivePath(bip32Path); | ||
| const publicKey = await nodeAdapter.getPublicKey(); | ||
|
|
||
| // Compute actual contract address using OpenZeppelin account contract | ||
| const constructorCalldata = CallData.compile({ publicKey }); | ||
| const contractAddress = hash.calculateContractAddressFromHash( | ||
| publicKey, | ||
| this.OZ_ACCOUNT_CLASS_HASH, | ||
| constructorCalldata, | ||
| 0 | ||
| ); | ||
|
|
||
| // Ensure contract address is zero-padded to 64 hex chars (Starknet spec) | ||
| const paddedAddress = contractAddress.startsWith("0x") | ||
| ? "0x" + contractAddress.slice(2).padStart(64, "0") | ||
| : "0x" + contractAddress.padStart(64, "0"); | ||
|
|
||
| return paddedAddress; | ||
| } | ||
|
|
||
| /** | ||
| * Sign Starknet transaction | ||
| * Starknet uses ECDSA on the STARK curve for transaction signing | ||
| */ | ||
| async signTransaction(txHash: string, addressNList: core.BIP32Path): Promise<string[]> { | ||
| const bip32Path = core.addressNListToBIP32(addressNList); | ||
| const nodeAdapter = await this.nodeAdapter.derivePath(bip32Path); | ||
| const signature = await nodeAdapter.node.sign(txHash); | ||
| return [signature.r, signature.s]; | ||
| } | ||
| } | ||
|
|
||
| export default StarknetAdapter; |
3 changes: 2 additions & 1 deletion
3
packages/hdwallet-native/src/crypto/isolation/core/bip32/interfaces.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
packages/hdwallet-native/src/crypto/isolation/core/stark/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { derivePath } from "../bip32"; | ||
| export * from "./interfaces"; |
40 changes: 40 additions & 0 deletions
40
packages/hdwallet-native/src/crypto/isolation/core/stark/interfaces.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { Revocable } from ".."; | ||
| import { ChainCode } from "../bip32"; | ||
|
|
||
| /** | ||
| * Stark curve Node interface for Starknet | ||
| * | ||
| * OVERVIEW: | ||
| * Implements hierarchical deterministic key derivation for Starknet using the STARK curve. | ||
| * Uses standard BIP32 secp256k1 derivation math (per SLIP-0010 and industry standard), | ||
| * then applies Starknet-specific key grinding for public key generation and signing. | ||
| * | ||
| * STARK CURVE: | ||
| * - Weierstrass curve: y² = x³ + ax + b (mod p) | ||
| * - Prime field: p = 2^251 + 17×2^192 + 1 (251-bit, not 256-bit like secp256k1) | ||
| * - Parameters: a = 1, b = π | ||
| * - Different from secp256k1, requires separate implementation | ||
| * - Spec: https://docs.starkware.co/starkex/crypto/stark-curve.html | ||
| * | ||
| * KEY METHODS: | ||
| * - getPublicKey(): Returns Stark public key (after grinding) as hex string | ||
| * - sign(): ECDSA signature on STARK curve, returns {r, s} with 64-char hex padding | ||
| * - derive(): BIP32 child key derivation using secp256k1 field arithmetic | ||
| * | ||
| * REFERENCES: | ||
| * - STARK Curve: https://docs.starkware.co/starkex/crypto/stark-curve.html | ||
| * - Key Grinding: https://docs.starkware.co/starkex/crypto/key-derivation.html | ||
| * - Starknet Cryptography: https://docs.starknet.io/architecture/cryptography/ | ||
| * - SLIP-0010: https://github.com/satoshilabs/slips/blob/master/slip-0010.md | ||
| */ | ||
| export interface Node extends Partial<Revocable> { | ||
| readonly explicitPath?: string; | ||
| /** Get Stark public key (applies key grinding, returns hex string) */ | ||
| getPublicKey(): Promise<string>; | ||
| /** Get BIP32 chain code for derivation */ | ||
| getChainCode(): Promise<ChainCode>; | ||
| /** Derive child key using BIP32 secp256k1 math (per industry standard) */ | ||
| derive(index: number): Promise<this>; | ||
| /** Sign transaction hash on STARK curve (returns padded 64-char hex r,s) */ | ||
| sign(txHash: string): Promise<{ r: string; s: string }>; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.