Skip to content

Commit

Permalink
Ledger: handle *All, *Many transactions (#375)
Browse files Browse the repository at this point in the history
Co-authored-by: Chi Kei Chan <chikeichan@gmail.com>
  • Loading branch information
rithvikvibhu and chikeichan authored Jul 9, 2021
1 parent 192102a commit f8c2cbd
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 35 deletions.
11 changes: 2 additions & 9 deletions app/background/wallet/bulk-renewal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { states } = require("hsd/lib/covenants/namestate");
const MTX = require("hsd/lib/primitives/mtx");
const Output = require("hsd/lib/primitives/output");

export const renewMany = async (wallet, names) => {
export const createRenewMany = async (wallet, names) => {
if (!Array.isArray(names)) {
throw new Error("names must be an array");
}
Expand Down Expand Up @@ -71,12 +71,5 @@ export const renewMany = async (wallet, names) => {
mtx.outputs.push(output);
}

const unlock = await wallet.fundLock.lock();
try {
await wallet.fill(mtx);
const finalizedTX = await wallet.finalize(mtx);
await wallet.sendMTX(finalizedTX, null);
} finally {
unlock();
}
return mtx;
};
22 changes: 4 additions & 18 deletions app/background/wallet/bulk-transfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const {states} = require('hsd/lib/covenants/namestate');
const MTX = require('hsd/lib/primitives/mtx');
const Output = require('hsd/lib/primitives/output');

export const transferMany = async (wallet, names, recipientAddress) => {
export const createTransferMany = async (wallet, names, recipientAddress) => {
if (!Array.isArray(names)) {
throw new Error('names must be an array');
}
Expand Down Expand Up @@ -64,17 +64,10 @@ export const transferMany = async (wallet, names, recipientAddress) => {
mtx.outputs.push(output);
}

const unlock = await wallet.fundLock.lock();
try {
await wallet.fill(mtx);
const finalizedTX = await wallet.finalize(mtx);
await wallet.sendMTX(finalizedTX, null);
} finally {
unlock();
}
return mtx;
};

export const finalizeMany = async (wallet, names) => {
export const createFinalizeMany = async (wallet, names) => {
if (!Array.isArray(names)) {
throw new Error('names must be an array');
}
Expand Down Expand Up @@ -143,12 +136,5 @@ export const finalizeMany = async (wallet, names) => {
mtx.outputs.push(output);
}

const unlock = await wallet.fundLock.lock();
try {
await wallet.fill(mtx);
const finalizedTX = await wallet.finalize(mtx);
await wallet.sendMTX(finalizedTX, null);
} finally {
unlock();
}
return mtx;
};
88 changes: 80 additions & 8 deletions app/background/wallet/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {
} from '../../ducks/walletReducer';
import {SET_FEE_INFO, SET_NODE_INFO} from "../../ducks/nodeReducer";
import createRegisterAll from "./create-register-all";
import {finalizeMany, transferMany} from "./bulk-transfer";
import {renewMany} from "./bulk-renewal";
import {createFinalizeMany, createTransferMany} from "./bulk-transfer";
import {createRenewMany} from "./bulk-renewal";
import {getStats} from "./stats";
import {get, put} from "../db/service";
import hsdLedger from 'hsd-ledger';
Expand Down Expand Up @@ -473,9 +473,7 @@ class WalletService {
const unlock = await wallet.fundLock.lock();

try {
await wallet.fill(mtx);
const finalizedTX = await wallet.finalize(mtx);
await wallet.sendMTX(finalizedTX, null);
return this._ledgerSendCustomTx(wallet, mtx);
} finally {
unlock();
}
Expand All @@ -484,19 +482,40 @@ class WalletService {
transferMany = async (names, address) => {
const {wdb} = this.node;
const wallet = await wdb.get(this.name);
await transferMany(wallet, names, address);
const mtx = await createTransferMany(wallet, names, address);
const unlock = await wallet.fundLock.lock();

try {
return this._ledgerSendCustomTx(wallet, mtx);
} finally {
unlock();
}
};

finalizeMany = async (names) => {
const {wdb} = this.node;
const wallet = await wdb.get(this.name);
await finalizeMany(wallet, names);
const mtx = await createFinalizeMany(wallet, names);
const unlock = await wallet.fundLock.lock();

try {
return this._ledgerSendCustomTx(wallet, mtx);
} finally {
unlock();
}
};

renewMany = async (names) => {
const {wdb} = this.node;
const wallet = await wdb.get(this.name);
await renewMany(wallet, names);
const mtx = await createRenewMany(wallet, names);
const unlock = await wallet.fundLock.lock();

try {
return this._ledgerSendCustomTx(wallet, mtx);
} finally {
unlock();
}
};

sendRevealAll = () => this._ledgerProxy(
Expand Down Expand Up @@ -1234,6 +1253,59 @@ class WalletService {
}, onNonLedger, false);
};

async _ledgerSendCustomTx(wallet, mtx) {
await wallet.fill(mtx);
const finalizedTX = await wallet.finalize(mtx);

if (wallet.watchOnly) {
return await this._ledgerProxy(
// With ledger: create ledger inputs that include path
async () => {
const options = {
inputs: await this._ledgerInputs(wallet, finalizedTX),
}
return [finalizedTX.getJSON(this.network), options];
},
// No ledger: unused
async () => {
return finalizedTX;
},
true, // shouldConfirmLedger (ledger only)
true // broadcast (ledger only)
);
} else {
return await wallet.sendMTX(finalizedTX, null);
}
}

async _ledgerInputs(wallet, tx) {
// For mtx created in Bob (instead of hsd), the inputs don't include
// path, so they need to be recreated as LedgerInput
const ledgerInputs = [];

for (const [idx, input] of tx.inputs.entries()) {
const coin = await wallet.getCoin(input.prevout.hash, input.prevout.index);
const key = await wallet.getKey(coin.address);
const publicKey = key.publicKey;
const path =
'm/' + // master
'44\'/' + // purpose
`${this.network.keyPrefix.coinType}'/` + // coin type
`${key.account}'/` + // should be 0 ("default")
`${key.branch}/` + // should be 1 (change)
`${key.index}`;
const ledgerInput = new LedgerInput({
publicKey,
path,
coin,
input,
index: idx,
})
ledgerInputs.push(ledgerInput)
}
return ledgerInputs;
}

async _executeRPC(method, args, cb) {
await this._selectWallet();
const res = await this.client.execute(method, args);
Expand Down

0 comments on commit f8c2cbd

Please sign in to comment.