Meriadec Pillet
7 years ago
committed by
GitHub
19 changed files with 236 additions and 218 deletions
@ -1,141 +0,0 @@ |
|||||
/* eslint-disable no-console */ |
|
||||
|
|
||||
const CommNodeHid = require('@ledgerhq/hw-transport-node-hid').default |
|
||||
const Btc = require('@ledgerhq/hw-app-btc').default |
|
||||
|
|
||||
const { CREATE } = process.env |
|
||||
|
|
||||
const { |
|
||||
createWallet, |
|
||||
createAccount, |
|
||||
createAmount, |
|
||||
getCurrency, |
|
||||
getWallet, |
|
||||
syncAccount, |
|
||||
signTransaction, |
|
||||
} = require('@ledgerhq/ledger-core') |
|
||||
|
|
||||
async function getOrCreateWallet(currencyId) { |
|
||||
try { |
|
||||
const wallet = await getWallet(currencyId) |
|
||||
return wallet |
|
||||
} catch (err) { |
|
||||
const currency = await getCurrency(currencyId) |
|
||||
const wallet = await createWallet(currencyId, currency) |
|
||||
return wallet |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
async function scanNextAccount(wallet, hwApp, accountIndex = 0) { |
|
||||
console.log(`creating an account with index ${accountIndex}`) |
|
||||
const account = await createAccount(wallet, hwApp) |
|
||||
console.log(`synchronizing account ${accountIndex}`) |
|
||||
await syncAccount(account) |
|
||||
console.log(`finished sync`) |
|
||||
const utxoCount = await account.asBitcoinLikeAccount().getUTXOCount() |
|
||||
console.log(`utxoCount = ${utxoCount}`) |
|
||||
} |
|
||||
|
|
||||
async function scanAccountsOnDevice(props) { |
|
||||
try { |
|
||||
const { devicePath, currencyId } = props |
|
||||
console.log(`get or create wallet`) |
|
||||
const wallet = await getOrCreateWallet(currencyId) |
|
||||
console.log(`open device`) |
|
||||
const transport = await CommNodeHid.open(devicePath) |
|
||||
console.log(`create app`) |
|
||||
const hwApp = new Btc(transport) |
|
||||
console.log(`scan account`) |
|
||||
const accounts = await scanNextAccount(wallet, hwApp) |
|
||||
console.log(accounts) |
|
||||
return [] |
|
||||
} catch (err) { |
|
||||
console.log(err) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
waitForDevices(async device => { |
|
||||
// const accounts = await scanAccountsOnDevice({
|
|
||||
// devicePath: device.path,
|
|
||||
// currencyId: 'bitcoin_testnet',
|
|
||||
// })
|
|
||||
// console.log(accounts)
|
|
||||
try { |
|
||||
console.log(`> Creating transport`) |
|
||||
const transport = await CommNodeHid.open(device.path) |
|
||||
|
|
||||
// transport.setDebugMode(true)
|
|
||||
|
|
||||
console.log(`> Instanciate BTC app`) |
|
||||
const hwApp = new Btc(transport) |
|
||||
|
|
||||
console.log(`> Get currency`) |
|
||||
const currency = await getCurrency('bitcoin_testnet') |
|
||||
|
|
||||
console.log(`> Create wallet`) |
|
||||
const wallet = CREATE ? await createWallet('khalil', currency) : await getWallet('khalil') |
|
||||
|
|
||||
console.log(`> Create account`) |
|
||||
const account = CREATE ? await createAccount(wallet, hwApp) : await wallet.getAccount(0) |
|
||||
|
|
||||
console.log(`> Sync account`) |
|
||||
if (CREATE) { |
|
||||
await syncAccount(account) |
|
||||
} |
|
||||
|
|
||||
console.log(`> Create transaction`) |
|
||||
const transaction = await createTransaction(wallet, account) |
|
||||
const signedTransaction = await signTransaction(hwApp, transaction) |
|
||||
|
|
||||
await account.asBitcoinLikeAccount().broadcastRawTransaction(signedTransaction) |
|
||||
// console.log(signedTransaction);
|
|
||||
|
|
||||
process.exit(0) |
|
||||
// console.log(account.getIndex());
|
|
||||
// console.log(account.isSynchronizing());
|
|
||||
} catch (err) { |
|
||||
console.log(err.message) |
|
||||
process.exit(1) |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
function waitForDevices(onDevice) { |
|
||||
console.log(`> Waiting for device...`) |
|
||||
CommNodeHid.listen({ |
|
||||
error: () => {}, |
|
||||
complete: () => {}, |
|
||||
next: async e => { |
|
||||
if (!e.device) { |
|
||||
return |
|
||||
} |
|
||||
if (e.type === 'add') { |
|
||||
console.log(`> Detected ${e.device.manufacturer} ${e.device.product}`) |
|
||||
onDevice(e.device) |
|
||||
} |
|
||||
if (e.type === 'remove') { |
|
||||
console.log(`removed ${JSON.stringify(e)}`) |
|
||||
} |
|
||||
}, |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
async function createTransaction(wallet, account) { |
|
||||
const ADDRESS_TO_SEND = 'n2jdejywRogCunR2ozZAfXp1jMnfGpGXGR' |
|
||||
|
|
||||
const bitcoinLikeAccount = account.asBitcoinLikeAccount() |
|
||||
const walletCurrency = wallet.getCurrency() |
|
||||
const amount = createAmount(walletCurrency, 10000) |
|
||||
|
|
||||
console.log(`--------------------------------`) |
|
||||
console.log(amount.toLong()) |
|
||||
console.log(`-----------------after `) |
|
||||
const fees = createAmount(walletCurrency, 1000) |
|
||||
|
|
||||
const transactionBuilder = bitcoinLikeAccount.buildTransaction() |
|
||||
transactionBuilder.sendToAddress(amount, ADDRESS_TO_SEND) |
|
||||
// TODO: don't use hardcoded value for sequence (and first also maybe)
|
|
||||
transactionBuilder.pickInputs(0, 0xffffff) |
|
||||
transactionBuilder.setFeesPerByte(fees) |
|
||||
|
|
||||
return transactionBuilder.build() |
|
||||
} |
|
@ -0,0 +1,22 @@ |
|||||
|
// @flow
|
||||
|
|
||||
|
import React from 'react' |
||||
|
import type { Account } from '@ledgerhq/live-common/lib/types' |
||||
|
|
||||
|
import CurrentAddress from 'components/CurrentAddress' |
||||
|
|
||||
|
type Props = { |
||||
|
account: Account, |
||||
|
} |
||||
|
|
||||
|
export default function CurrentAddressForAccount(props: Props) { |
||||
|
const { account, ...p } = props |
||||
|
|
||||
|
// TODO: handle other cryptos than BTC-like
|
||||
|
let freshAddress = account.addresses[0] |
||||
|
if (!freshAddress) { |
||||
|
freshAddress = { str: '', path: '' } |
||||
|
} |
||||
|
|
||||
|
return <CurrentAddress accountName={account.name} address={freshAddress.str} {...p} /> |
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
// @flow
|
||||
|
|
||||
|
import Btc from '@ledgerhq/hw-app-btc' |
||||
|
import CommNodeHid from '@ledgerhq/hw-transport-node-hid' |
||||
|
import type { AccountRaw } from '@ledgerhq/live-common/lib/types' |
||||
|
|
||||
|
import type Transport from '@ledgerhq/hw-transport' |
||||
|
|
||||
|
import type { IPCSend } from 'types/electron' |
||||
|
import { getWalletIdentifier } from '../scanAccountsOnDevice' |
||||
|
|
||||
|
type BitcoinLikeTransaction = { |
||||
|
amount: number, |
||||
|
feePerByte: number, |
||||
|
recipient: string, |
||||
|
} |
||||
|
|
||||
|
export default async function signAndBroadcastTransactionBTCLike( |
||||
|
send: IPCSend, |
||||
|
{ |
||||
|
account, |
||||
|
transaction, |
||||
|
deviceId, // which is in fact `devicePath`
|
||||
|
}: { |
||||
|
account: AccountRaw, |
||||
|
transaction: BitcoinLikeTransaction, |
||||
|
deviceId: string, |
||||
|
}, |
||||
|
) { |
||||
|
try { |
||||
|
// TODO: investigate why importing it on file scope causes trouble
|
||||
|
const core = require('init-ledger-core')() |
||||
|
|
||||
|
// instanciate app on device
|
||||
|
const transport: Transport<*> = await CommNodeHid.open(deviceId) |
||||
|
const hwApp = new Btc(transport) |
||||
|
|
||||
|
const WALLET_IDENTIFIER = await getWalletIdentifier({ |
||||
|
hwApp, |
||||
|
isSegwit: account.isSegwit, |
||||
|
currencyId: account.currencyId, |
||||
|
devicePath: deviceId, |
||||
|
}) |
||||
|
|
||||
|
const njsWallet = await core.getWallet(WALLET_IDENTIFIER) |
||||
|
const njsAccount = await njsWallet.getAccount(account.index) |
||||
|
const bitcoinLikeAccount = njsAccount.asBitcoinLikeAccount() |
||||
|
const njsWalletCurrency = njsWallet.getCurrency() |
||||
|
const amount = core.createAmount(njsWalletCurrency, transaction.amount) |
||||
|
const fees = core.createAmount(njsWalletCurrency, transaction.feePerByte) |
||||
|
const transactionBuilder = bitcoinLikeAccount.buildTransaction() |
||||
|
|
||||
|
// TODO: check if is valid address. if not, it will fail silently on invalid
|
||||
|
|
||||
|
transactionBuilder.sendToAddress(amount, transaction.recipient) |
||||
|
// TODO: don't use hardcoded value for sequence (and first also maybe)
|
||||
|
transactionBuilder.pickInputs(0, 0xffffff) |
||||
|
transactionBuilder.setFeesPerByte(fees) |
||||
|
|
||||
|
const builded = await transactionBuilder.build() |
||||
|
const signedTransaction = await core.signTransaction(hwApp, builded) |
||||
|
|
||||
|
const txHash = await njsAccount |
||||
|
.asBitcoinLikeAccount() |
||||
|
.broadcastRawTransaction(signedTransaction) |
||||
|
|
||||
|
send('accounts.signAndBroadcastTransactionBTCLike.success', txHash) |
||||
|
} catch (err) { |
||||
|
send('accounts.signAndBroadcastTransactionBTCLike.fail', err) |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue