Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions lib/glueby/internal/wallet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ def fill_uncolored_inputs(
[tx, fee, current_amount, provided_utxos]
end

def import_private_key(key, label = nil)
wallet_adapter.import_private_key(id, key, label)
end

private

def wallet_adapter
Expand Down
13 changes: 13 additions & 0 deletions lib/glueby/internal/wallet/abstract_wallet_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,19 @@ def get_addresses(wallet_id, label = nil)
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
end

# Import a private key to the wallet
#
# CAUTION: Wallet Adapter doesn't rescan blockchain for the imported privatekey.
# So the UTXOs in processed blocks are not counted on the Glueby::BlockSyncer.
#
Comment thread
azuchi marked this conversation as resolved.
# @param [String] wallet_id - The private key is imported to.
# @param [Tapyrus::Key] key - The private key that is imported to the wallet.
# @param [String?] label - The label to filter the addresses.
# @raise [Errors::PrivateKeyAlreadyImported] If the private key already imported to the wallet.
Comment thread
azuchi marked this conversation as resolved.
def import_private_key(wallet_id, key, label = nil)
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
end

# Create and returns pay to contract address
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
# @param [String] contents - The data to be used for generating pay-to-contract address
Expand Down
24 changes: 24 additions & 0 deletions lib/glueby/internal/wallet/active_record_wallet_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,30 @@ def get_addresses(wallet_id, label = nil)
keys.map(&:address)
end

def import_private_key(wallet_id, key, label = nil)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

引数の型チェックを追加してください。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

型チェックを追加しました

raise Glueby::ArgumentError, 'key should be a Tapyrus::Key' unless key.is_a?(Tapyrus::Key)
raise Glueby::ArgumentError, 'label should be a String' if label && !label.is_a?(String)

wallet = AR::Wallet.find_by(wallet_id: wallet_id)
ar_key = AR::Key.find_by(
wallet: wallet,
private_key: key.priv_key,
public_key: key.pubkey
)
if ar_key
raise Errors::PrivateKeyAlreadyImported, "Key(pubkey: #{key.pubkey}) already imported in the wallet(#{wallet_id})"
else
AR::Key.create!(
wallet: wallet,
private_key: key.priv_key,
public_key: key.pubkey,
label: label,
purpose: :receive
)
end
nil
end

def get_addresses_info(addresses)
unless addresses.is_a?(Array)
addresses = [addresses]
Expand Down
1 change: 1 addition & 0 deletions lib/glueby/internal/wallet/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class WalletAlreadyCreated < Error; end
class WalletNotFound < Error; end
class InvalidSighashType < Error; end
class InvalidSigner < Error; end
class PrivateKeyAlreadyImported < Error; end
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/glueby/wallet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def id
@internal_wallet.id
end

def import_private_key(key, label = nil)
@internal_wallet.import_private_key(key, label)
end

# @return [HashMap] hash of balances which key is color_id or empty string, and value is amount
def balances(only_finalized = true)
utxos = @internal_wallet.list_unspent(only_finalized)
Expand Down
59 changes: 59 additions & 0 deletions spec/glueby/internal/wallet/active_record_wallet_adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,65 @@
end
end

describe '#import_private_key' do
let(:key) { Tapyrus::Key.generate }
subject { adapter.import_private_key(wallet.wallet_id, key) }

it 'create a new Key record' do
expect { subject }.to change { Glueby::Internal::Wallet::AR::Key.count }.by(1)

ar_key = Glueby::Internal::Wallet::AR::Key.where(public_key: key.pubkey).first
expect(ar_key.private_key).to eq(key.priv_key)
expect(ar_key.script_pubkey).to eq(Tapyrus::Script.to_p2pkh(Tapyrus.hash160(key.pubkey)).to_hex)
expect(ar_key.label).to be_nil
expect(ar_key.purpose).to eq('receive')
end

context 'key is not an instance of Tapyrus::Key' do
let(:key) { 'invalid key' }

it 'create a new Key record' do
expect { subject }.to raise_error(Glueby::ArgumentError, 'key should be a Tapyrus::Key')
end
end

context 'specify label' do
let(:label) { 'test_label' }
subject { adapter.import_private_key(wallet.wallet_id, key, label) }

it 'the new Key record has label' do
subject
ar_key = Glueby::Internal::Wallet::AR::Key.where(public_key: key.pubkey).first
expect(ar_key.label).to eq('test_label')
end

context 'label is not an instance of String' do
let(:label) { 123 }
it 'create a new Key record' do
expect { subject }.to raise_error(Glueby::ArgumentError, 'label should be a String')
end
end
end

context 'the private key is already in the wallet' do
before do
Glueby::Internal::Wallet::AR::Key.create!(
wallet: wallet,
private_key: key.priv_key,
public_key: key.pubkey,
purpose: :receive
)
end

it 'create a new Key record' do
expect { subject }.to raise_error(
Glueby::Internal::Wallet::Errors::PrivateKeyAlreadyImported,
"Key(pubkey: #{key.pubkey}) already imported in the wallet(#{wallet.wallet_id})"
)
end
end
Comment thread
azuchi marked this conversation as resolved.
end

describe '#get_addresses_info' do
subject { adapter.get_addresses_info(addresses) }

Expand Down
13 changes: 13 additions & 0 deletions spec/glueby/wallet_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ def list_unspent(wallet_id, only_finalized = true, label = nil, color_id: nil)
def token_utxos(wallet_id, color_id, only_finalized, per, page)
[]
end

def import_private_key(wallet_id, key, label = nil)
true
end
end

before { Glueby::Internal::Wallet.wallet_adapter = TestWalletAdapter.new }
Expand Down Expand Up @@ -160,4 +164,13 @@ def token_utxos(wallet_id, color_id, only_finalized, per, page)
expect(Glueby::Internal::Wallet.wallet_adapter).to have_received(:list_unspent_with_count).with("wallet_id:1", only_finalized, nil, color_id: color_id, page: 1, per: 25)
end
end

describe '#import_private_key' do
let(:key) { Tapyrus::Key.generate }
let(:wallet) { Glueby::Wallet.create }

it 'returns true' do
expect(wallet.import_private_key(key, 'test-label')).to eq(true)
end
end
Comment thread
azuchi marked this conversation as resolved.
end