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

Enhance wallet class #159

Merged
merged 29 commits into from
Sep 20, 2018
Merged

Enhance wallet class #159

merged 29 commits into from
Sep 20, 2018

Conversation

usatie
Copy link
Member

@usatie usatie commented Sep 18, 2018

Description of the Change

Implement high level class Wallet.
Now everyone can send/receive Bitcoin with only 10 lines.

// 1. Create Private Key, Publick Key, Address
let privkey: PrivateKey = PrivateKey(network: .mainnet)
let pubkey: PublicKey = privkey.publicKey()
let address: Cashaddr = pubkey.toCashaddr()
let qrImage: UIImage? = address.qrImage(size: CGSize(width: 240, height: 240))

// 2. Create Wallet, Get balance, Refresh balance
let wallet: Wallet = Wallet(privateKey: privkey,
                            walletDataStore: UserDefaults.standard)
let balance = wallet.balance
wallet.reloadBalance()

// 3. Send Bitcoin
let toAddress = try! AddressFactory.create("bitcoincash:qz936smm809wq0eqthqyh2sgdzhs7v08nvnuq0dmps")
wallet.send(to: toAddress, amount: 10000)

AddressProvider, UtxoProvider, TransactionHistoryProvider

Basically, both reload() and list() are methods for retrieving addresses, utxos and transactions. The difference between them is that reload() is async method, while list() is sync method.

Alternate Designs

None.

Benefits

More beginner welcome!

Possible Drawbacks

None.

Applicable Issues

closes #156

@usatie usatie requested a review from akifuji September 18, 2018 10:45
@usatie usatie added the enhancement New feature or request label Sep 18, 2018
let vout: UInt32
let sequence: UInt32
let scriptSig: ScriptSig
// let addr: String
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are they comment out? Please comment the reason somewhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

These are part of API response, but not used.

So I commented them out.

import Foundation

public protocol AddressProvider {
// GET API: reload utxos
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is inappropriate, isn't it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh it isn't. I'll fix it.

import Foundation

public protocol TransactionBuilder {
func build(destinations: [(address: Address, amount: UInt64)], utxos: [UnspentTransaction]) throws -> UnsignedTransaction
Copy link
Contributor

Choose a reason for hiding this comment

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

The name might be confusing.
TransactionBuilder should build Transaction not UnsignedTransaction

Copy link
Member Author

Choose a reason for hiding this comment

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

I think the name is okay with this. But I think the name of Transaction and UnsignedTransaction are the problem.

Copy link
Member Author

Choose a reason for hiding this comment

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

UnsignedTransaction is almost just a wrap of Transaction and UnspentOutput

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay


import Foundation

public protocol TransactionProvider {
Copy link
Contributor

@akifuji akifuji Sep 18, 2018

Choose a reason for hiding this comment

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

Again, this one is also confusing.
How about TransactionHistoryProvider .

Copy link
Member Author

Choose a reason for hiding this comment

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

This is true. I'll change it.

import Foundation

public protocol TransactionProvider {
// GET API: reload transactions
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this function would not be only with API, but also SPV or something.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes

import Foundation

public protocol UtxoProvider {
// GET API: reload utxos
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as TransactionProvider .
Do not need to limit only API.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes


// MARK: - WalletDataStoreProtocol Extension
internal enum WalletDataStoreKey: String {
case wif, internalIndex, extenralIndex
Copy link
Contributor

Choose a reason for hiding this comment

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

This protocol is not for HDWallet, isn't it?
Then, I think internalIndex and extenralIndex are not necessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

This protocol will be for HDWallet as well.


public protocol AddressProvider {
// GET API: reload utxos
func reload(keys: [PrivateKey], completion: (([Address]) -> Void)?)
Copy link
Contributor

@akifuji akifuji Sep 18, 2018

Choose a reason for hiding this comment

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

I cannot understand the reason why this function is necessary.
Is it enough to convert PrivateKey into Address?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, converting PrivateKey to Address is not enough.
Mainly this protocol is for P2SH.

Someone may want to compute new P2SH addresses using the keys outside as well as the keys inside by using API or some other way.


public func reload(keys: [PrivateKey], completion: (([Address]) -> Void)?) {
let data = try? JSONEncoder().encode(keys.map { $0.publicKey().toCashaddr() })
userDefaults.set(data, forKey: UserDefaultsKey.cashaddrs.rawValue)
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need to add completion?()?

utxoSelector: UtxoSelector = StandardUtxoSelector.default,
transactionBuilder: TransactionBuilder = StandardTransactionBuilder.default,
transactionSigner: TransactionSigner = StandardTransactionSigner.default) {
guard let privkey = try? PrivateKey(wif: wif) else {
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

guard let wif = walletDataStore.getString(forKey: .wif) else {
return nil
}
guard let privkey = try? PrivateKey(wif: wif) else {
Copy link
Contributor

Choose a reason for hiding this comment

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

typo


func createWalletIfNeeded() {
if wallet == nil {
let privkey = PrivateKey(network: .testnet)
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

qrCodeImageView.image = wallet?.address.qrImage()
addressLabel.text = wallet?.address.cashaddr
if let balance = wallet?.balance() {
balanceLabel.text = "残高:\(balance) satoshi"
Copy link
Contributor

Choose a reason for hiding this comment

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

Use English

// ViewController.swift
// WalletExample
//
// Created by Shun Usami on 2018/09/18.
Copy link
Contributor

Choose a reason for hiding this comment

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

Change copyright

public struct BitcoinComEndpoint {
public static let testnet: BitcoinComEndpoint = BitcoinComEndpoint(baseUrl: "https://trest.bitcoin.com/v1/")
public static let mainnet: BitcoinComEndpoint = BitcoinComEndpoint(baseUrl: "https://rest.bitcoin.com/v1/")
public struct ApiEndPoint {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should you modify file name too?

Copy link
Contributor

@akifuji akifuji left a comment

Choose a reason for hiding this comment

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

LGTM

@akifuji akifuji merged commit 62b5aec into master Sep 20, 2018
@usatie usatie deleted the enhance-wallet-class branch September 22, 2018 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement higher level of abstraction such as sendTo(address:), balance()
2 participants