Skip to content

Commit

Permalink
chore: Fix Mnemonic Seed Wallet import Specify Network ID
Browse files Browse the repository at this point in the history
  • Loading branch information
John-peterson-coinbase committed Jan 17, 2025
1 parent 494cc92 commit 17d6839
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CDP Python SDK Changelog

## Unreleased

### Fixed

- Allow wallet mnemonic seed import to optionally accept `network_id` input argument.

## [0.14.0] - 2025-01-14

### Added
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ lint-fix:

.PHONY: test
test:
poetry run pytest
poetry run pytest -m "not e2e"

.PHONY: e2e
e2e:
Expand Down
5 changes: 3 additions & 2 deletions cdp/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,14 @@ def list(cls) -> Iterator["Wallet"]:
page = response.next_page

@classmethod
def import_wallet(cls, data: WalletData | MnemonicSeedPhrase) -> "Wallet":
def import_wallet(cls, data: WalletData | MnemonicSeedPhrase, network_id: str = "base-sepolia") -> "Wallet":
"""Import a wallet from previously exported wallet data or a mnemonic seed phrase.
Args:
data (Union[WalletData, MnemonicSeedPhrase]): Either:
- WalletData: The wallet data to import, containing wallet_id and seed
- MnemonicSeedPhrase: A valid BIP-39 mnemonic phrase object for importing external wallets
network_id (str): The network ID of the wallet. Defaults to "base-sepolia".
Returns:
Wallet: The imported wallet.
Expand All @@ -291,7 +292,7 @@ def import_wallet(cls, data: WalletData | MnemonicSeedPhrase) -> "Wallet":
seed = seed_bytes.hex()

# Create wallet using the provided seed
wallet = cls.create_with_seed(seed=seed)
wallet = cls.create_with_seed(seed=seed, network_id=network_id)
wallet._set_addresses()
return wallet

Expand Down
62 changes: 62 additions & 0 deletions tests/test_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,68 @@ def test_wallet_import_from_mnemonic_seed_phrase(
assert wallet.default_address._model.public_key == public_key


@patch("cdp.Cdp.use_server_signer", False)
@patch("cdp.Cdp.api_clients")
@patch("cdp.wallet.Account")
def test_wallet_import_from_mnemonic_seed_phrase_specified_network_id(
mock_account,
mock_api_clients,
wallet_factory,
address_model_factory,
):
"""Test importing a wallet from a mnemonic seed phrase with network ID specified."""
# Valid 24-word mnemonic and expected address
valid_mnemonic = "crouch cereal notice one canyon kiss tape employ ghost column vanish despair eight razor laptop keen rally gaze riot regret assault jacket risk curve"
expected_address = "0x43A0477E658C6e05136e81C576CF02daCEa067bB"
public_key = "0x037e6cbdd1d949f60f41d5db7ffa9b3ddce0b77eab35ef7affd3f64cbfd9e33a91"

# Create mock address model
mock_address = address_model_factory(
address_id=expected_address,
public_key=public_key,
wallet_id="new-wallet-id",
network_id="base-mainnet",
index=0,
)

# Create mock wallet model with the address model
mock_wallet = wallet_factory(
id="new-wallet-id", network_id="base-mainnet", default_address=mock_address
)._model

# Add debug assertions
assert mock_wallet.default_address is not None
assert mock_wallet.default_address.address_id == expected_address

# Mock Account.from_key to return an account with our expected address
mock_account_instance = Mock(spec=Account)
mock_account_instance.address = expected_address
mock_account.from_key = Mock(return_value=mock_account_instance)

# Mock both API calls to return the same wallet model
mock_api_clients.wallets.create_wallet = Mock(return_value=mock_wallet)
mock_api_clients.wallets.get_wallet = Mock(return_value=mock_wallet)
mock_api_clients.addresses.create_address = Mock(return_value=mock_address)

# Mock list_addresses call
mock_address_list = Mock()
mock_address_list.data = [mock_address]
mock_api_clients.addresses.list_addresses = Mock(return_value=mock_address_list)

# Import wallet using mnemonic
from cdp.mnemonic_seed_phrase import MnemonicSeedPhrase

wallet = Wallet.import_wallet(MnemonicSeedPhrase(valid_mnemonic), network_id="base-mainnet")

# Verify the wallet was created successfully
assert isinstance(wallet, Wallet)

# Verify the default address matches expected address
assert wallet.default_address is not None
assert wallet.default_address.address_id == expected_address
assert wallet.default_address._model.public_key == public_key


def test_wallet_import_from_mnemonic_empty_phrase():
"""Test importing a wallet with an empty mnemonic phrase."""
from cdp.mnemonic_seed_phrase import MnemonicSeedPhrase
Expand Down

0 comments on commit 17d6839

Please sign in to comment.