Skip to content
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

feat(PSDK-670): Support external wallet imports, wallet imports from CDP Python SDK #347

Merged
merged 14 commits into from
Dec 19, 2024

Conversation

derek-cb
Copy link

@derek-cb derek-cb commented Dec 17, 2024

What changed? Why?

  • Support external 1-of-1 wallet import via BIP-39 mnemonic phrases (12, 15, 18, 21, or 24 words)
  • Support import of wallet data exported from CDP Python SDK
  • Renamed saveSeed() to saveSeedtoFile(), and deprecated the former
  • Renamed loadSeed() to loadSeedFromFile(), and deprecated the former
  • Added retry mechanism to address.listTransactions() E2E test for better resiliency

Testing

Tested via:

  • Import of 12, 15, 18, 21, and 24-word mnemonic seed phrases
  • Export of wallets generated via mnemonic seed phrases
  • Import of wallets generated via mnemonic seed phrases, that were then exported
  • Successfully imported wallet exported from CDP Python SDK v0.12.0
  • Successfully imported wallet exported from CDP NodeJS SDK v0.11.0

Qualified Impact

… 18, 21, or 24 words)

- Support import of wallet data exported from CDP Python SDK
- Deprecated existing Wallet.import() method in favor of Wallet.load() (more descriptive of the fact that we're loading an existing CDP wallet, not importing one into CDP)
- Renamed loadSeed() to loadSeedFromFile(), and deprecated the former
- Merged mnemonic phrase import into the import() method
- Merged WalletData and WalletDataSnake into one type, for clarity in method args
- Updated unit tests
# Conflicts:
#	src/coinbase/types.ts
#	src/coinbase/wallet.ts
# Conflicts:
#	src/coinbase/types.ts
#	src/coinbase/wallet.ts
Comment on lines +819 to +823
/**
* The CDP wallet ID in either camelCase or snake_case format, but not both.
*/
walletId?: string;
wallet_id?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option to try to enforce mutual exclusivity is to use never:

type WalletData = {
    walletId: string;
    wallet_id?: never;
} | {
    walletId?: never;
    wallet_id: string;
}

const walletData: WalletData = {
    walletId: '123',
    wallet_id: '123'
}

Now TypeScript will error with a message:

Type '{ walletId: string; wallet_id: string; }' is not assignable to type 'WalletData'.
  Types of property 'wallet_id' are incompatible.
    Type 'string' is not assignable to type 'undefined'

Admittedly, the error message could be clearer, but it's difficult to customize the message without reaching for a type validation library like Zod, which might be overkill here.

*/
export type WalletData = {
walletId: string;
export interface WalletData {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on reasoning to convert this from a type to an interface?


// Convert mnemonic phrase to seed
const seedBuffer = mnemonicToSeedSync(data.mnemonicPhrase);
const seed = hexlify(seedBuffer).slice(2); // remove 0x prefix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably out-of-scope for this PR, but I would love to switch to viem and/or Ox.

That said, we do already have viem installed as a dependency, so we could use toHex instead!


// Create wallet using the provided seed
const wallet = await Wallet.createWithSeed({
seed: seed,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Shorthand syntax can be used here (this should be enforced ideally by the linter / formatter, I'll make a note of it)

// Create wallet using the provided seed
const wallet = await Wallet.createWithSeed({
seed: seed,
networkId: Coinbase.networks.BaseSepolia,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should networkId be parameterized?

*
* @param options - The options to create the Wallet.
* @param options.seed - The seed to use for the Wallet. If undefined, a random seed will be generated.
* @param options.networkId - the ID of the blockchain network. Defaults to 'base-sepolia'.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the is lowercased here, but uppercased in the other strings

Copy link
Contributor

@0xRAG 0xRAG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments & nits, but nothing blocking. 🚢

Comment on lines +9 to +10
- Deprecate `Wallet.loadSeed()` method in favor of `Wallet.loadSeedFromFile()`
- Deprecate `Wallet.saveSeed()` method in favor of `Wallet.saveSeedToFile()`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll move these around as we prep the release, but we'll have a separate heading for "Address" and "Deprecated"

@@ -130,31 +136,67 @@ export class Wallet {
}

/**
* Imports a Wallet for the given Wallet data.
* Loads an existing CDP Wallet using a wallet data object or mnemonic seed phrase.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we document that it creates a new wallet for mnemonic seed phrases?

Or how can we best clarify that this leaves the existing behavior + adds new behavior, and lays the groundwork for the breaking change in the next release?

Not a blocker per se, but we should aim to make this clear in our public docs + here when we make the cutover

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes great point. FYI this didn't make it into this PR, so will add a comment within our breaking changes to-list just to track

Copy link
Contributor

@alex-stone alex-stone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I think having a big rev on the docs around wallet import v.s. wallet load, etc... is going to be important in the next 2 releases

@alex-stone alex-stone merged commit ac9d252 into v0.13.0 Dec 19, 2024
4 checks passed
@alex-stone alex-stone deleted the feat/external-wallet-import branch December 19, 2024 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants