it('Should supplement wallet generation with fees', co(function *() { const fees = [{ open: '10', median: '6000', expected: '9000' }, { open: '7000', median: '4000', expected: '10500' }]; for (const currentFees of fees) { nock('https://test.bitgo.com/api/v2/txrp/public') .get('/feeinfo') .reply(200, { date: '2017-10-18T18:28:13.083Z', height: 3353255, xrpBaseReserve: '20000000', xrpIncReserve: '5000000', xrpOpenLedgerFee: currentFees.open, xrpMedianFee: currentFees.median }); const details = yield nockBasecoin.supplementGenerateWallet({}, keychains); const disableMasterKey = rippleBinaryCodec.decode(details.initializationTxs.disableMasterKey); const forceDestinationTag = rippleBinaryCodec.decode(details.initializationTxs.forceDestinationTag); const setMultisig = rippleBinaryCodec.decode(details.initializationTxs.setMultisig); disableMasterKey.Fee.should.equal(currentFees.expected); forceDestinationTag.Fee.should.equal(currentFees.expected); setMultisig.Fee.should.equal(currentFees.expected); } }));
/** * Explain/parse transaction * @param params * - txHex: hexadecimal representation of transaction * @returns {{displayOrder: [string,string,string,string,string], id: *, outputs: Array, changeOutputs: Array}} */ public explainTransaction(params: ExplainTransactionOptions): TransactionExplanation { let transaction; let txHex; try { transaction = rippleBinaryCodec.decode(params.txHex); txHex = params.txHex; } catch (e) { try { transaction = JSON.parse(params.txHex); txHex = rippleBinaryCodec.encode(transaction); } catch (e) { throw new Error('txHex needs to be either hex or JSON string for XRP'); } } const id = rippleHashes.computeBinaryTransactionHash(txHex); const address = transaction.Destination + ((transaction.DestinationTag >= 0) ? '?dt=' + transaction.DestinationTag : ''); return { displayOrder: ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee'], id: id, changeOutputs: [], outputAmount: transaction.Amount, changeAmount: 0, outputs: [ { address, amount: transaction.Amount } ], fee: { fee: transaction.Fee, feeRate: null, size: txHex.length / 2 } }; }
const signWithPrivateKey = function(txHex, privateKey, options) { let privateKeyBuffer = new Buffer(privateKey, 'hex'); if (privateKeyBuffer.length === 33 && privateKeyBuffer[0] === 0) { privateKeyBuffer = privateKeyBuffer.slice(1, 33); } const privateKeyObject = prova.ECPair.fromPrivateKeyBuffer(privateKeyBuffer); const publicKey = privateKeyObject.getPublicKeyBuffer().toString('hex').toUpperCase(); let tx; try { tx = binary.decode(txHex); } catch (e) { try { tx = JSON.parse(txHex); } catch (e) { throw new Error('txHex needs to be either hex or JSON string for XRP'); } } if (tx.TxnSignature || tx.Signers) { throw new Error('transaction must not contain "TxnSignature" or "Signers" properties'); } tx.SigningPubKey = (options && options.signAs) ? '' : publicKey; if (options && options.signAs) { const expectedSigner = rippleKeypairs.deriveAddress(publicKey); if (options.signAs !== expectedSigner) { throw new Error('signAs does not match private key'); } const signer = { Account: options.signAs, SigningPubKey: publicKey, TxnSignature: computeSignature(tx, privateKey, options.signAs) }; tx.Signers = [{ Signer: signer }]; } else { tx.TxnSignature = computeSignature(tx, privateKey, undefined); } const serialized = binary.encode(tx); return { signedTransaction: serialized, id: computeBinaryTransactionHash(serialized) }; };