Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
5805196
WIP: poc-signer
claudiovb Dec 2, 2025
8a4dc0c
WIP: poc-signer
claudiovb Dec 3, 2025
e04a862
add ISignerEvm
claudiovb Dec 4, 2025
4c77e8c
add ISignerEvm
claudiovb Dec 4, 2025
4f18ce8
feat: add ledger signer evm
sontuphan Dec 8, 2025
2bd8427
fix: lint standardjs
sontuphan Dec 8, 2025
c00a22e
fix: add deps
sontuphan Dec 8, 2025
fc31010
fix: remote master node in bip44 derivation path in ledger signer
sontuphan Dec 9, 2025
6dbfe99
fix: add private async connect
sontuphan Dec 16, 2025
5af6f0a
Merge pull request #1 from sontuphan/poc-ledger-signer
claudiovb Dec 23, 2025
3a6b289
fix signer
claudiovb Dec 23, 2025
1734267
add safety checks to ledger signer
claudiovb Dec 23, 2025
bb9f608
fix sendTransaction
claudiovb Dec 23, 2025
ccdcfb9
fix derive function
claudiovb Dec 23, 2025
c4a879f
Merge branch 'tetherto:main' into poc-signer
claudiovb Dec 24, 2025
db2ff81
clean up for publishing
claudiovb Dec 24, 2025
f921284
update readme code
claudiovb Dec 24, 2025
f9fb077
refactor ledger submodule
claudiovb Dec 24, 2025
d937ab8
remove not used signer config object
claudiovb Dec 25, 2025
123e995
add missing method to ledger signer
claudiovb Dec 26, 2025
b2d6660
fix: bump dmk versions, fix minor bugs, autogen signer types
sontuphan Feb 12, 2026
d03a102
Merge pull request #3 from sontuphan/fix/poc-signer
claudiovb Feb 12, 2026
b901da8
fix: remove isActive and update ledger dispose
sontuphan Apr 8, 2026
9372233
Plain object signers fix, update packages
claudiovb Apr 8, 2026
8c12540
Merge changes
claudiovb Apr 10, 2026
cbc2d6c
Merge changes
claudiovb Apr 17, 2026
84b8cb1
fixes
claudiovb Apr 17, 2026
86d0061
Update src/signers/seed-signer-evm.js
claudiovb Apr 21, 2026
4b03dc9
Update src/signers/ledger-signer-evm.js
claudiovb Apr 21, 2026
997cbb5
defaults in the description not in brackets
claudiovb Apr 21, 2026
9f94876
Merge branch 'poc-signer' of github.com:claudiovb/wdk-wallet-evm into…
claudiovb Apr 21, 2026
cefe0a9
Small JSDOC fixes
claudiovb Apr 21, 2026
a213e11
Split test for signers & ISignerEVM contract fullfilment
claudiovb Apr 21, 2026
6a378b8
Merge with new updates
claudiovb Apr 29, 2026
bf11299
Fix JSDOCS issues
claudiovb May 4, 2026
3a041e0
Fix Ledger signing and unneeded guard clauses
claudiovb May 4, 2026
65576ed
Fix tests comments
claudiovb May 4, 2026
432aac7
Update types
claudiovb May 4, 2026
e615962
Update types and JSdocs small polishes
claudiovb May 4, 2026
109ba85
merge changes from main
claudiovb Jun 17, 2026
d979205
refactor to conform with new wdk-wallet implementation
claudiovb Jun 17, 2026
eb47d2c
fix bug from ricardo comment
claudiovb Jun 18, 2026
d81a6d0
update not needed tests and jsdoc definitions
claudiovb Jun 18, 2026
aeb52e3
minor fixes
claudiovb Jun 18, 2026
64ea4b9
update derive so its compatible with baseClass, refactor for better d…
claudiovb Jun 18, 2026
03cba9d
update package to published wdk-wallet version
claudiovb Jun 19, 2026
13cf4ac
don't pin peerdeps to avoid issue on consumers that use ledger instal…
claudiovb Jun 19, 2026
e4a0235
merge with changes on main
claudiovb Jun 19, 2026
3a2e0cd
address Ricardo's comments
claudiovb Jun 19, 2026
cfe141e
update with main
claudiovb Jun 24, 2026
a264337
update to to be nullable for allowing sc creation
claudiovb Jun 25, 2026
0dcd6a8
add test to validate smart contract creation
claudiovb Jun 25, 2026
49a3f3e
remove ledger from this branch
claudiovb Jun 25, 2026
74b3ea9
add fromPrivateKey static method to EVM
claudiovb Jun 25, 2026
6bc4b85
update wdk-wallet dep type
claudiovb Jun 26, 2026
815d022
update JSDOC
claudiovb Jun 26, 2026
853525f
remove useless guard on getAddress
claudiovb Jun 26, 2026
79c41bd
remove stale ts text
claudiovb Jun 26, 2026
ad224c6
update wdk-wallet to latest version
claudiovb Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
coverage
.vscode
.DS_Store
.vscode
308 changes: 284 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,288 @@ This module is part of the [**WDK (Wallet Development Kit)**](https://docs.wdk.t

For detailed documentation about the complete WDK ecosystem, visit [docs.wdk.tether.io](https://docs.wdk.tether.io).

## Installation
## ⬇️ Installation

To install the `@tetherto/wdk-wallet-evm` package, follow these instructions:

You can install it using npm:

```bash
npm install @tetherto/wdk-wallet-evm
```

## Quick Start
## 🚀 Quick Start

### Importing from `@tetherto/wdk-wallet-evm`

```javascript
import WalletManagerEvm, {
WalletAccountEvm,
WalletAccountReadOnlyEvm,
} from '@tetherto/wdk-wallet-evm'

// Signers are exported under the /signers subpath
import {
SeedSignerEvm,
PrivateKeySignerEvm,
} from '@tetherto/wdk-wallet-evm/signers'
```

### Create a Wallet Manager (seed-based)

```javascript
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import { SeedSignerEvm } from '@tetherto/wdk-wallet-evm/signers'

// Use a BIP-39 seed phrase (replace with your own secure phrase)
const seedPhrase =
'test only example nut use this real life secret phrase must random'

// Create a root signer from the seed phrase
const root = new SeedSignerEvm(seedPhrase)

const seedPhrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
// Create wallet manager with provider config (provider is required for chain ops)
const wallet = new WalletManagerEvm(root, {
// Option 1: Using RPC URL
provider: 'https://sepolia.drpc.org', // any EVM RPC
transferMaxFee: 100000000000000n, // Optional: max fee in wei (BigInt)
})

// OR

const wallet = new WalletManagerEvm(seedPhrase, {
provider: 'https://sepolia.drpc.org',
// Option 2: Using EIP-1193 provider (e.g., from browser wallet)
const wallet2 = new WalletManagerEvm(root, {
provider: window.ethereum, // EIP-1193 provider
transferMaxFee: 100000000000000n, // Optional
})

const account = await wallet.getAccount(0)
const address = await account.getAddress()
console.log('Address:', address)
// Get a full access account
const account0 = await wallet.getAccount(0)

// Convert to a read-only account
const readOnlyAccount = await account0.toReadOnlyAccount()
```

### Single Account (no manager): Private key

```javascript
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
import { PrivateKeySignerEvm } from '@tetherto/wdk-wallet-evm/signers'

// From a raw private key (hex string or bytes)
const pkSigner = new PrivateKeySignerEvm('0x0123...abcd')
const pkAccount = new WalletAccountEvm(pkSigner, {
provider: 'https://eth-mainnet.g.alchemy.com/v2/your-api-key',
})
```

### Managing Multiple Accounts (seed-based manager)

```javascript
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import { SeedSignerEvm } from '@tetherto/wdk-wallet-evm/signers'

const root = new SeedSignerEvm(mnemonic)
const wallet = new WalletManagerEvm(root, {
provider: 'https://eth-mainnet.g.alchemy.com/v2/your-api-key',
})

// Get the first account (index 0)
const account = await wallet.getAccount(0) // m/44'/60'/0'/0/0
const address = await account.getAddress() // 0x...
console.log('Account 0 address:', address)

// Get the second account (index 1)
const account1 = await wallet.getAccount(1) // m/44'/60'/0'/0/1
const address1 = await account1.getAddress() // 0x...
console.log('Account 1 address:', address1)

// Get account by custom derivation path
// Full path will be m/44'/60'/0'/0/5
const customAccount = await wallet.getAccountByPath('0\'/0/5')
const customAddress = await customAccount.getAddress()
console.log('Custom account address:', customAddress)

// Note: All addresses are checksummed Ethereum addresses (0x...)
// All accounts inherit the provider configuration from the wallet manager
```

### Checking Balances

#### Owned Account

For accounts where you have the seed phrase and full access:

```javascript
// Assume wallet and account are already created
// Get native token balance (in wei)
const balance = await account.getBalance()
console.log('Native balance:', balance, 'wei') // 1 ETH = 1000000000000000000 wei

// Get ERC20 token balance
const tokenContract = '0x...' // ERC20 contract address
const tokenBalance = await account.getTokenBalance(tokenContract)
console.log('Token balance:', tokenBalance)

// Note: Provider is required for balance checks
// Make sure wallet was created with a provider configuration
```

#### Read-Only Account

For addresses where you don't have the seed phrase:

```javascript
import { WalletAccountReadOnlyEvm } from '@tetherto/wdk-wallet-evm'

// Create a read-only account
const readOnlyAccount = new WalletAccountReadOnlyEvm('0x...', {
// Ethereum address
provider: 'https://sepolia.drpc.org', // Required for balance checks
})

// Check native token balance
const balance = await readOnlyAccount.getBalance()
console.log('Native balance:', balance, 'wei')

// Check ERC20 token balance using contract
const tokenBalance = await readOnlyAccount.getTokenBalance('0x...') // ERC20 contract address
console.log('Token balance:', tokenBalance)

// Note: ERC20 balance checks use the standard balanceOf(address) function
// Make sure the contract address is correct and implements the ERC20 standard
```

### Sending Transactions

Send native tokens and estimate fees using `WalletAccountEvm`. Supports EIP-1559 and auto-populates gas/fee fields where possible.

```javascript
// Send native tokens
// Modern EIP-1559 style transaction (recommended)
const result = await account.sendTransaction({
to: '0x...', // Recipient address
value: 1000000000000000000n, // 1 ETH in wei
maxFeePerGas: 30000000000n, // Optional: max fee per gas (in wei)
maxPriorityFeePerGas: 2000000000n, // Optional: max priority fee per gas (in wei)
})
console.log('Transaction hash:', result.hash)
console.log('Transaction fee:', result.fee, 'wei')

// OR Legacy style transaction
const legacyResult = await account.sendTransaction({
to: '0x...',
value: 1000000000000000000n,
gasPrice: 20000000000n, // Optional: legacy gas price (in wei)
gasLimit: 21000, // Optional: gas limit
})

// Get transaction fee estimate
const quote = await account.quoteSendTransaction({
to: '0x...',
value: 1000000000000000000n,
})
console.log('Estimated fee:', quote.fee, 'wei')
```

### Token Transfers

Transfer ERC20 tokens and estimate fees using `WalletAccountEvm`. Uses standard ERC20 `transfer` function.

```javascript
// Transfer ERC20 tokens
const transferResult = await account.transfer({
token: '0x...', // ERC20 contract address
recipient: '0x...', // Recipient's address
amount: 1000000n, // Amount in token's base units (use BigInt for large numbers)
})
console.log('Transfer hash:', transferResult.hash)
console.log('Transfer fee:', transferResult.fee, 'wei')

// Quote token transfer fee
const transferQuote = await account.quoteTransfer({
token: '0x...', // ERC20 contract address
recipient: '0x...', // Recipient's address
amount: 1000000n, // Amount in token's base units
})
console.log('Transfer fee estimate:', transferQuote.fee, 'wei')
```

### Token Approvals

Approve a spender for a specific amount (uses ERC20 `approve`):

```javascript
const approval = await account.approve({
token: '0x...', // ERC20 contract
spender: '0x...', // Spender address
amount: 1000000n, // Allowance amount in base units
})
console.log('Approval tx hash:', approval.hash)
```

### Message Signing and Verification

Sign messages using `WalletAccountEvm` and verify signatures using `WalletAccountReadOnlyEvm`.

```javascript
// Sign a message
const message = 'Hello, Ethereum!'
const signature = await account.sign(message)
console.log('Signature:', signature)

// Verify a signature (can use read-only account)
const isValid = await readOnlyAccount.verify(message, signature)
console.log('Signature valid:', isValid)
```

### Fee Management

Retrieve current fee rates using `WalletManagerEvm`. Supports EIP-1559 fee model.

```javascript
// Get current fee rates
const feeRates = await wallet.getFeeRates()
console.log('Normal fee rate:', feeRates.normal, 'wei') // 1.1x base fee
console.log('Fast fee rate:', feeRates.fast, 'wei') // 2.0x base fee
```

### Memory Management

Clear sensitive data from memory using `dispose` methods in `WalletAccountEvm` and `WalletManagerEvm`.

```javascript
// Dispose wallet accounts to clear private keys from memory
account.dispose()

// Dispose entire wallet manager
wallet.dispose()
```

## 🔐 Signers

Signers provide the cryptographic primitives for accounts. There are two signer implementations:

- **SeedSignerEvm (root + child)**: Derives accounts from a BIP-39 seed using the BIP-44 Ethereum path. Can act as a root (for `WalletManagerEvm`) and derive children (for `WalletAccountEvm`).
- **PrivateKeySignerEvm (child only)**: Wraps a raw private key in a memory-safe buffer. Cannot derive. Use directly with `WalletAccountEvm`. Not supported by `WalletManagerEvm`.

Examples:

```javascript
// Root + manager (seed)
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import { SeedSignerEvm } from '@tetherto/wdk-wallet-evm/signers'
const root = new SeedSignerEvm(mnemonic)
const wallet = new WalletManagerEvm(root, { provider: 'https://...' })
const account0 = await wallet.getAccount(0)

// Single account from a private key
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
import { PrivateKeySignerEvm } from '@tetherto/wdk-wallet-evm/signers'
const signer = new PrivateKeySignerEvm('0x0123...')
const account = new WalletAccountEvm(signer, { provider: 'https://...' })
```

## Key Capabilities

- **BIP-39 Seed Phrase Support**: Generate and validate mnemonic seed phrases
Expand All @@ -49,6 +307,8 @@ wallet.dispose()
- **Message Signing**: Sign and verify messages (EIP-191 and EIP-712)
- **Fee Estimation**: Real-time network fee rates with normal/fast tiers
- **Secure Memory Disposal**: Clear private keys from memory when done
- **Signer Submodule**: Create your own signer from ISignerEvm, support for Seed and Private key signers
- **EIP-7702 Delegation**: Delegate EOAs to smart contracts, sign authorizations, and send type 4 transactions

## Compatibility

Expand All @@ -58,26 +318,26 @@ wallet.dispose()

## Documentation

| Topic | Description | Link |
|-------|-------------|------|
| Overview | Module overview and feature summary | [Wallet EVM Overview](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm) |
| Usage | End-to-end integration walkthrough | [Wallet EVM Usage](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm/usage) |
| Topic | Description | Link |
| ------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------- |
| Overview | Module overview and feature summary | [Wallet EVM Overview](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm) |
| Usage | End-to-end integration walkthrough | [Wallet EVM Usage](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm/usage) |
| Configuration | Provider, fees, and network configuration | [Wallet EVM Configuration](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm/configuration) |
| API Reference | Complete class and type reference | [Wallet EVM API Reference](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm/api-reference) |
| API Reference | Complete class and type reference | [Wallet EVM API Reference](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm/api-reference) |

## Examples

| Example | Description |
|---------|-------------|
| [Create Wallet](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/create-wallet.ts) | Initialize a wallet manager and derive accounts from a seed phrase |
| [Manage Accounts](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/manage-accounts.ts) | Work with multiple accounts and custom derivation paths |
| [Check Balances](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/check-balances.ts) | Query native token and ERC-20 balances for owned accounts |
| [Read-Only Account](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/read-only-account.ts) | Monitor balances for any address without a private key |
| [Send Transaction](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/send-transaction.ts) | Estimate fees and send native token transactions (EIP-1559 + legacy) |
| [Token Transfer](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/token-transfer.ts) | Transfer ERC-20 tokens and estimate transfer fees |
| [Sign & Verify Message](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/sign-verify-message.ts) | Sign messages and verify signatures |
| [Fee Management](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/fee-management.ts) | Retrieve current network fee rates |
| [Memory Management](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/memory-management.ts) | Securely dispose wallets and clear private keys from memory |
| Example | Description |
| ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| [Create Wallet](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/create-wallet.ts) | Initialize a wallet manager and derive accounts from a seed phrase |
| [Manage Accounts](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/manage-accounts.ts) | Work with multiple accounts and custom derivation paths |
| [Check Balances](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/check-balances.ts) | Query native token and ERC-20 balances for owned accounts |
| [Read-Only Account](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/read-only-account.ts) | Monitor balances for any address without a private key |
| [Send Transaction](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/send-transaction.ts) | Estimate fees and send native token transactions (EIP-1559 + legacy) |
| [Token Transfer](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/token-transfer.ts) | Transfer ERC-20 tokens and estimate transfer fees |
| [Sign & Verify Message](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/sign-verify-message.ts) | Sign messages and verify signatures |
| [Fee Management](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/fee-management.ts) | Retrieve current network fee rates |
| [Memory Management](https://github.com/tetherto/wdk-examples/blob/main/wallet-evm/memory-management.ts) | Securely dispose wallets and clear private keys from memory |

> For detailed walkthroughs, see the [Usage Guide](https://docs.wdk.tether.io/sdk/wallet-modules/wallet-evm/usage).
> See all runnable examples in the [wdk-examples](https://github.com/tetherto/wdk-examples) repository.
Expand Down
2 changes: 2 additions & 0 deletions index.js
Comment thread
Davi0kProgramsThings marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

/** @typedef {import('./src/wallet-account-evm.js').ApproveOptions} ApproveOptions */

/** @typedef {import('./src/utils/tx-populator-evm.js').UnsignedEvmTransaction} UnsignedEvmTransaction */

export { default } from './src/wallet-manager-evm.js'

export { default as WalletAccountReadOnlyEvm } from './src/wallet-account-read-only-evm.js'
Expand Down
Loading