Skip to content

Commit

Permalink
Merge pull request #75 from kevinheavey/hdwallets
Browse files Browse the repository at this point in the history
Add Keypair.from_seed_and_derivation_path
  • Loading branch information
kevinheavey authored Dec 30, 2023
2 parents 1c58dd3 + 0aeff3a commit bf85b74
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 42 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
maturin-version: ${{ env.maturin_version }}
- name: Install built wheel
run: |
pip install pytest pytest-asyncio based58 pybip39 typing-extensions jsonalias
pip install pytest pytest-asyncio based58 pybip39 mnemonic typing-extensions jsonalias
pip install ${{ env.name }} --no-index --no-dependencies --find-links dist --force-reinstall
pytest
Expand All @@ -61,7 +61,7 @@ jobs:
maturin-version: ${{ env.maturin_version }}
- name: Install built wheel
run: |
pip install pytest pytest-asyncio based58 pybip39 typing-extensions jsonalias
pip install pytest pytest-asyncio based58 pybip39 mnemonic typing-extensions jsonalias
pip install ${{ env.name }} --no-index --no-dependencies --find-links dist --force-reinstall
pytest
- name: Upload wheels
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:
maturin-version: ${{ env.maturin_version }}
- name: Install built wheel
run: |
python -m pip install pytest pytest-asyncio based58 pybip39 typing-extensions jsonalias
python -m pip install pytest pytest-asyncio based58 pybip39 mnemonic typing-extensions jsonalias
python -m pip install ${{ env.name }} --no-index --no-dependencies --find-links dist --force-reinstall
python -m pytest --ignore=tests/bankrun
- name: Upload wheels
Expand Down Expand Up @@ -125,7 +125,7 @@ jobs:
- name: Install built wheel
if: matrix.target == 'x86_64'
run: |
pip install pytest pytest-asyncio based58 pybip39 typing-extensions jsonalias
pip install pytest pytest-asyncio based58 pybip39 mnemonic typing-extensions jsonalias
pip install ${{ env.name }} --no-index --no-dependencies --find-links dist --force-reinstall
pytest
- name: Upload wheels
Expand Down Expand Up @@ -189,7 +189,7 @@ jobs:
options: -v ${{ github.workspace }}:/io -w /io
run: |
apk add py3-pip
pip3 install -U pip pytest pytest-asyncio based58 pybip39 typing-extensions jsonalias --break-system-packages
pip3 install -U pip pytest pytest-asyncio based58 pybip39 mnemonic typing-extensions jsonalias --break-system-packages
pip3 install ${{ env.name }} --find-links /io/dist/ --force-reinstall --no-index --no-dependencies --break-system-packages
python3 -m pytest
- name: Upload wheels
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Added

- Add `Keypair.from_seed_and_derivation_path` [(#75)](https://github.com/kevinheavey/solders/pull/75)

### Fixed

- Fix (de)serialization of Account `owner` field [(#70)](https://github.com/kevinheavey/solders/pull/70)
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

---

[![Actions
Status](https://github.com/kevinheavey/solders/workflows/CI/badge.svg)](https://github.com/kevinheavey/solders/actions?query=workflow%3ACI)
[![PyPI version](https://badge.fury.io/py/solders.svg)](https://badge.fury.io/py/solders)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/kevinheavey/solders/blob/main/LICENSE)

Expand Down
36 changes: 32 additions & 4 deletions crates/keypair/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use derive_more::{From, Into};
use pyo3::{prelude::*, types::PyBytes};
use serde::{Deserialize, Serialize};
use solana_sdk::signer::{
keypair::{
keypair_from_seed, keypair_from_seed_phrase_and_passphrase, Keypair as KeypairOriginal,
use solana_sdk::{
derivation_path::DerivationPath,
signature::keypair_from_seed_and_derivation_path,
signer::{
keypair::{
keypair_from_seed, keypair_from_seed_phrase_and_passphrase, Keypair as KeypairOriginal,
},
Signer as SignerTrait,
},
Signer as SignerTrait,
};
use solders_macros::{common_methods, pyhash, richcmp_signer};
use solders_pubkey::Pubkey;
Expand Down Expand Up @@ -193,6 +197,30 @@ impl Keypair {
handle_py_value_err(keypair_from_seed(&seed))
}

#[staticmethod]
/// Generate a keypair from a 32-byte seed and derivation path..
///
/// Args:
/// seed (bytes): 32-byte seed.
/// dpath (str): derivation path.
/// Returns:
/// Keypair: The generated keypair.
///
/// Example:
/// >>> from solders.keypair import Keypair
/// >>> from solders.pubkey import Pubkey
/// >>> seed_bytes = bytes([0] * 64)
/// >>> account_index = 0
/// >>> derivation_path = f"m/44'/501'/0'/{account_index}'"
/// >>> from_seed = Keypair.from_seed_and_derivation_path(seed_bytes, derivation_path)
///
pub fn from_seed_and_derivation_path(seed: [u8; 64], dpath: &str) -> PyResult<Self> {
handle_py_value_err(keypair_from_seed_and_derivation_path(
&seed,
Some(DerivationPath::from_absolute_path_str(dpath).unwrap()),
))
}

#[staticmethod]
/// Generate a keypair from a seed phrase and passphrase.
///
Expand Down
1 change: 1 addition & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def python(session):
"typing-extensions",
"jsonalias",
"myst-parser",
"mnemonic",
)
session.install(".", "--no-build-isolation")
session.run("make", "test", external=True)
56 changes: 25 additions & 31 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ based58 = "0.1.1"
bumpversion = "0.6.0"
"jsonalias" = "0.1.1"
ruff = "0.1.6"
mnemonic = "0.20"
mypy = "0.991"
pytest = "7.2.1"
pytest-asyncio = "^0.20.3"
Expand Down
4 changes: 4 additions & 0 deletions python/solders/keypair.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class Keypair:
@staticmethod
def from_seed(seed: Union[bytes, Sequence[int]]) -> "Keypair": ...
@staticmethod
def from_seed_and_derivation_path(
seed: Union[bytes, Sequence[int]], dpath: str
) -> "Keypair": ...
@staticmethod
def from_base58_string(s: str) -> "Keypair": ...
@staticmethod
def from_seed_phrase_and_passphrase(
Expand Down
1 change: 1 addition & 0 deletions tests/test_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def test_pickle(account: Account) -> None:
def test_json(account: Account) -> None:
assert Account.from_json(account.to_json()) == account


def test_account_from_json() -> None:
# https://github.com/kevinheavey/solders/issues/69
raw = """{
Expand Down
10 changes: 10 additions & 0 deletions tests/test_keypair.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
from operator import ge, gt, le, lt
from typing import Any, Callable

import mnemonic
from pybip39 import Mnemonic, Seed
from pytest import mark, raises
from solders.keypair import Keypair


def test_from_seed_and_derivation_path() -> None:
mnemo = mnemonic.Mnemonic("english")
seed = mnemo.to_seed(
"pill tomorrow foster begin walnut borrow virtual kick shift mutual shoe scatter"
)
pubkey = Keypair.from_seed_and_derivation_path(seed, "m/44'/501'/0'/0'").pubkey()
assert str(pubkey) == "5F86TNSTre3CYwZd1wELsGQGhqG2HkN3d8zxhbyBSnzm"


def test_from_bytes() -> None:
raw_bytes = (
b"\x99\xda\x95Y\xe1^\x91>\xe9\xab.S\xe3\xdf\xadW]\xa3;I\xbe\x11%\xbb\x92.3IOI"
Expand Down
1 change: 1 addition & 0 deletions tests/test_rpc_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,7 @@ def test_get_program_accounts_without_context() -> None:
pubkey=Pubkey.from_string("CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY"),
)


def test_keyed_account_from_json() -> None:
raw = """{
"pubkey": "7wZpAKYM1uygtosoF42V4a5tVLsrzpSN6Uedaxc6vGrQ",
Expand Down

0 comments on commit bf85b74

Please sign in to comment.