Change prepare* methods to reject Promise on error (#984)

* Reject Promise on error, update docs, and add tests:
  * preparePayment
  * prepareTrustline
  * prepareOrder
  * prepareOrderCancellation
  * prepareSettings
  * prepareEscrowCreation
  * prepareEscrowExecution
  * prepareCheckCreate
  * prepareCheckCash
  * prepareCheckCancel
  * preparePaymentChannelCreate
  * preparePaymentChannelFund
  * preparePaymentChannelClaim

Note that we can't update mocha to ^5.2.0 because it causes testing to hang indefinitely; this needs to be investigated.
This commit is contained in:
Elliot Lee
2019-01-29 15:22:18 -08:00
committed by GitHub
parent dc148bf954
commit 2445004333
17 changed files with 491 additions and 115 deletions

View File

@@ -1,5 +1,53 @@
# ripple-lib Release History
## UNRELEASED
**BREAKING CHANGE:**
The `prepare*` methods now reject the Promise when an error occurs.
Previously, the methods would synchronously throw on validation errors, despite being asynchronous methods that return Promises.
In other words, to handle errors in the past, you would need to use a try/catch block:
```
// OBSOLETE - no need for try/catch anymore
try {
api.preparePayment(address, payment, instructions).then(prepared => {
res.send(prepared.txJSON);
}).catch(error => {
// Handle asynchronous error
});
} catch (error) {
// Handle synchronous error
}
```
Now, you can rely on the Promise's `catch` handler, which is called with the error when the Promise is rejected:
```
api.preparePayment(address, payment, instructions).then(prepared => {
res.send(prepared.txJSON);
}).catch(error => {
// Handle error
});
```
This applies to:
* preparePayment
* prepareTrustline
* prepareOrder
* prepareOrderCancellation
* prepareSettings
* prepareEscrowCreation
* prepareEscrowExecution
* prepareCheckCreate
* prepareCheckCash
* prepareCheckCancel
* preparePaymentChannelCreate
* preparePaymentChannelClaim
* preparePaymentChannelFund
## 1.1.2 (2018-12-12)
+ Update `submit` response (#978)

View File

@@ -4584,8 +4584,11 @@ const payment = {
}
}
};
return api.preparePayment(address, payment).then(prepared =>
{/* ... */});
return api.preparePayment(address, payment).then(prepared => {
/* ... */
}).catch(error => {
/* ... as with all prepare* methods, use a Promise catch block to handle errors ... */
})
```

View File

@@ -23,8 +23,11 @@ All "prepare*" methods have the same return type.
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const payment = <%- importFile('test/fixtures/requests/prepare-payment.json') %>;
return api.preparePayment(address, payment).then(prepared =>
{/* ... */});
return api.preparePayment(address, payment).then(prepared => {
/* ... */
}).catch(error => {
/* ... as with all prepare* methods, use a Promise catch block to handle errors ... */
})
```
<%- renderFixture("responses/prepare-payment.json") %>

View File

@@ -22,11 +22,15 @@ function prepareCheckCancel(address: string,
checkCancel: CheckCancel,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareCheckCancel(
{address, checkCancel, instructions})
const txJSON = createCheckCancelTransaction(
address, checkCancel)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareCheckCancel(
{address, checkCancel, instructions})
const txJSON = createCheckCancelTransaction(
address, checkCancel)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareCheckCancel

View File

@@ -40,11 +40,15 @@ function prepareCheckCash(address: string,
checkCash: CheckCash,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareCheckCash(
{address, checkCash, instructions})
const txJSON = createCheckCashTransaction(
address, checkCash)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareCheckCash(
{address, checkCash, instructions})
const txJSON = createCheckCashTransaction(
address, checkCash)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareCheckCash

View File

@@ -41,11 +41,15 @@ function prepareCheckCreate(address: string,
checkCreate: CheckCreate,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareCheckCreate(
{address, checkCreate, instructions})
const txJSON = createCheckCreateTransaction(
address, checkCreate)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareCheckCreate(
{address, checkCreate, instructions})
const txJSON = createCheckCreateTransaction(
address, checkCreate)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareCheckCreate

View File

@@ -56,11 +56,15 @@ function prepareEscrowCreation(address: string,
escrowCreation: EscrowCreation,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareEscrowCreation(
{address, escrowCreation, instructions})
const txJSON = createEscrowCreationTransaction(
address, escrowCreation)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareEscrowCreation(
{address, escrowCreation, instructions})
const txJSON = createEscrowCreationTransaction(
address, escrowCreation)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareEscrowCreation

View File

@@ -44,11 +44,15 @@ function prepareEscrowExecution(address: string,
escrowExecution: EscrowExecution,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareEscrowExecution(
{address, escrowExecution, instructions})
const txJSON = createEscrowExecutionTransaction(
address, escrowExecution)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareEscrowExecution(
{address, escrowExecution, instructions})
const txJSON = createEscrowExecutionTransaction(
address, escrowExecution)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareEscrowExecution

View File

@@ -47,9 +47,13 @@ function createOrderTransaction(
function prepareOrder(address: string, order: FormattedOrderSpecification,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareOrder({address, order, instructions})
const txJSON = createOrderTransaction(address, order)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareOrder({address, order, instructions})
const txJSON = createOrderTransaction(address, order)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareOrder

View File

@@ -20,9 +20,13 @@ function createOrderCancellationTransaction(account: string,
function prepareOrderCancellation(address: string, orderCancellation: object,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareOrderCancellation({address, orderCancellation, instructions})
const txJSON = createOrderCancellationTransaction(address, orderCancellation)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareOrderCancellation({address, orderCancellation, instructions})
const txJSON = createOrderCancellationTransaction(address, orderCancellation)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareOrderCancellation

View File

@@ -62,11 +62,15 @@ function preparePaymentChannelClaim(address: string,
paymentChannelClaim: PaymentChannelClaim,
instructions: Instructions = {}
): Promise<Prepare> {
validate.preparePaymentChannelClaim(
{address, paymentChannelClaim, instructions})
const txJSON = createPaymentChannelClaimTransaction(
address, paymentChannelClaim)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.preparePaymentChannelClaim(
{address, paymentChannelClaim, instructions})
const txJSON = createPaymentChannelClaimTransaction(
address, paymentChannelClaim)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default preparePaymentChannelClaim

View File

@@ -41,11 +41,15 @@ function preparePaymentChannelCreate(address: string,
paymentChannelCreate: PaymentChannelCreate,
instructions: Instructions = {}
): Promise<Prepare> {
validate.preparePaymentChannelCreate(
{address, paymentChannelCreate, instructions})
const txJSON = createPaymentChannelCreateTransaction(
address, paymentChannelCreate)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.preparePaymentChannelCreate(
{address, paymentChannelCreate, instructions})
const txJSON = createPaymentChannelCreateTransaction(
address, paymentChannelCreate)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default preparePaymentChannelCreate

View File

@@ -29,11 +29,15 @@ function preparePaymentChannelFund(address: string,
paymentChannelFund: PaymentChannelFund,
instructions: Instructions = {}
): Promise<Prepare> {
validate.preparePaymentChannelFund(
{address, paymentChannelFund, instructions})
const txJSON = createPaymentChannelFundTransaction(
address, paymentChannelFund)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.preparePaymentChannelFund(
{address, paymentChannelFund, instructions})
const txJSON = createPaymentChannelFundTransaction(
address, paymentChannelFund)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default preparePaymentChannelFund

View File

@@ -172,9 +172,13 @@ function createPaymentTransaction(address: string, paymentArgument: Payment
function preparePayment(address: string, payment: Payment,
instructions: Instructions = {}
): Promise<Prepare> {
validate.preparePayment({address, payment, instructions})
const txJSON = createPaymentTransaction(address, payment)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.preparePayment({address, payment, instructions})
const txJSON = createPaymentTransaction(address, payment)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default preparePayment

View File

@@ -8,7 +8,7 @@ const AccountFields = utils.common.constants.AccountFields
import {Instructions, Prepare} from './types'
import {FormattedSettings, WeightedSigner} from '../common/types/objects'
// Emptry string passed to setting will clear it
// Empty string passed to setting will clear it
const CLEAR_SETTING = null
function setTransactionFlags(txJSON: any, values: FormattedSettings) {
@@ -43,7 +43,7 @@ function setTransactionFields(txJSON: object, input: FormattedSettings) {
if (field.encoding === 'hex' && !field.length) {
// This is currently only used for Domain field
value = new Buffer(value, 'ascii').toString('hex').toUpperCase()
value = Buffer.from(value, 'ascii').toString('hex').toUpperCase()
}
txJSON[fieldName] = value
@@ -125,9 +125,13 @@ function createSettingsTransaction(account: string, settings: FormattedSettings
function prepareSettings(address: string, settings: FormattedSettings,
instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareSettings({address, settings, instructions})
const txJSON = createSettingsTransaction(address, settings)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareSettings({address, settings, instructions})
const txJSON = createSettingsTransaction(address, settings)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareSettings

View File

@@ -53,9 +53,13 @@ function createTrustlineTransaction(account: string,
function prepareTrustline(address: string,
trustline: FormattedTrustlineSpecification, instructions: Instructions = {}
): Promise<Prepare> {
validate.prepareTrustline({address, trustline, instructions})
const txJSON = createTrustlineTransaction(address, trustline)
return utils.prepareTransaction(txJSON, this, instructions)
try {
validate.prepareTrustline({address, trustline, instructions})
const txJSON = createTrustlineTransaction(address, trustline)
return utils.prepareTransaction(txJSON, this, instructions)
} catch (e) {
return Promise.reject(e)
}
}
export default prepareTrustline

View File

@@ -519,23 +519,170 @@ describe('RippleAPI', function () {
})
});
it('preparePayment - XRP to XRP no partial', function () {
assert.throws(() => {
this.api.preparePayment(address, requests.preparePayment.wrongPartial);
}, /XRP to XRP payments cannot be partial payments/);
});
describe('errors', function () {
it('preparePayment - address must match payment.source.address', function (
) {
assert.throws(() => {
this.api.preparePayment(address, requests.preparePayment.wrongAddress);
}, /address must match payment.source.address/);
});
const senderAddress = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const recipientAddress = 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo';
it('preparePayment - wrong amount', function () {
assert.throws(() => {
this.api.preparePayment(address, requests.preparePayment.wrongAmount);
}, this.api.errors.ValidationError);
it('rejects promise and does not throw when payment object is invalid', function (done) {
const payment = {
source: {
address: senderAddress,
amount: { // instead of `maxAmount`
value: '1000',
currency: 'drops'
}
},
destination: {
address: recipientAddress,
amount: {
value: '1000',
currency: 'drops'
}
}
}
// Cannot use `assert.rejects` because then the test passes (with UnhandledPromiseRejectionWarning) even when it should not.
// See https://github.com/mochajs/mocha/issues/3097
try {
this.api.preparePayment(senderAddress, payment).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'payment must specify either (source.maxAmount and destination.amount) or (source.amount and destination.minAmount)');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('rejects promise and does not throw when field is missing', function (done) {
const payment = {
source: {
address: senderAddress
// `maxAmount` missing
},
destination: {
address: recipientAddress,
amount: {
value: '1000',
currency: 'drops'
}
}
}
// Cannot use `assert.rejects` because then the test passes (with UnhandledPromiseRejectionWarning) even when it should not.
// See https://github.com/mochajs/mocha/issues/3097
try {
this.api.preparePayment(senderAddress, payment).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.payment.source is not exactly one from <sourceExactAdjustment>,<maxAdjustment>');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('rejects promise and does not throw when fee exceeds maxFeeXRP', function (done) {
const payment = {
source: {
address: senderAddress,
maxAmount: {
value: '1000',
currency: 'drops'
}
},
destination: {
address: recipientAddress,
amount: {
value: '1000',
currency: 'drops'
}
}
}
// Cannot use `assert.rejects` because then the test passes (with UnhandledPromiseRejectionWarning) even when it should not.
// See https://github.com/mochajs/mocha/issues/3097
try {
this.api.preparePayment(senderAddress, payment, {
fee: '3' // XRP
}).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'Fee of 3 XRP exceeds max of 2 XRP. To use this fee, increase `maxFeeXRP` in the RippleAPI constructor.');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('preparePayment - XRP to XRP no partial', function (done) {
try {
// Cannot return promise because we want/expect it to reject.
this.api.preparePayment(address, requests.preparePayment.wrongPartial).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'XRP to XRP payments cannot be partial payments');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('preparePayment - address must match payment.source.address', function (done) {
try {
// Cannot return promise because we want/expect it to reject.
this.api.preparePayment(address, requests.preparePayment.wrongAddress).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'address must match payment.source.address');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('preparePayment - wrong amount', function (done) {
try {
// Cannot return promise because we want/expect it to reject.
this.api.preparePayment(address, requests.preparePayment.wrongAmount).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'payment must specify either (source.maxAmount and destination.amount) or (source.amount and destination.minAmount)');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('preparePayment - throws when fee exceeds 2 XRP', function (done) {
const localInstructions = _.defaults({
fee: '2.1'
}, instructions);
try {
// Cannot return promise because we want/expect it to reject.
this.api.preparePayment(
address, requests.preparePayment.normal, localInstructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'Fee of 2.1 XRP exceeds max of 2 XRP. To use this fee, increase `maxFeeXRP` in the RippleAPI constructor.');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
});
it('preparePayment with all options specified', function () {
@@ -565,17 +712,6 @@ describe('RippleAPI', function () {
responses.preparePayment.minAmount, 'prepare'));
});
it('preparePayment - throws when fee exceeds 2 XRP', function () {
const localInstructions = _.defaults({
fee: '2.1'
}, instructions);
assert.throws(() => {
this.api.preparePayment(
address, requests.preparePayment.normal, localInstructions)
}, /Fee of 2\.1 XRP exceeds max of 2 XRP\. To use this fee, increase `maxFeeXRP` in the RippleAPI constructor\./)
});
it('preparePayment - caps fee at 2 XRP by default', function () {
this.api._feeCushion = 1000000;
@@ -633,6 +769,22 @@ describe('RippleAPI', function () {
_.partial(checkResult, responses.prepareOrder.sell, 'prepare'));
});
it('prepareOrder - invalid', function (done) {
const request = requests.prepareOrder.sell;
delete request.direction; // Make invalid
try {
this.api.prepareOrder(address, request, instructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.order requires property "direction"');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareOrderCancellation', function () {
const request = requests.prepareOrderCancellation.simple;
return this.api.prepareOrderCancellation(address, request, instructions)
@@ -656,6 +808,22 @@ describe('RippleAPI', function () {
'prepare'));
});
it('prepareOrderCancellation - invalid', function (done) {
const request = requests.prepareOrderCancellation.withMemos;
delete request.orderSequence; // Make invalid
try {
this.api.prepareOrderCancellation(address, request).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.orderCancellation requires property "orderSequence"');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareTrustline - simple', function () {
return this.api.prepareTrustline(
address, requests.prepareTrustline.simple, instructions).then(
@@ -674,6 +842,23 @@ describe('RippleAPI', function () {
_.partial(checkResult, responses.prepareTrustline.complex, 'prepare'));
});
it('prepareTrustline - invalid', function (done) {
const trustline = requests.prepareTrustline.complex;
delete trustline.limit; // Make invalid
try {
this.api.prepareTrustline(
address, trustline, instructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.trustline requires property "limit"');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareSettings', function () {
return this.api.prepareSettings(
address, requests.prepareSettings.domain, instructions).then(
@@ -756,18 +941,34 @@ describe('RippleAPI', function () {
'prepare'));
});
it('prepareSettings - signers no threshold', function () {
it('prepareSettings - signers no threshold', function (done) {
const settings = requests.prepareSettings.signers.noThreshold;
assert.throws(() => {
this.api.prepareSettings(address, settings, instructions);
}, this.api.errors.ValidationError);
try {
this.api.prepareSettings(address, settings, instructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.settings.signers requires property "threshold"');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareSettings - signers no weights', function () {
it('prepareSettings - signers no weights', function (done) {
const settings = requests.prepareSettings.signers.noWeights;
assert.throws(() => {
this.api.prepareSettings(address, settings, instructions);
}, this.api.errors.ValidationError);
try {
this.api.prepareSettings(address, settings, instructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.settings.signers requires property "weights"');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareSettings - fee for multisign', function () {
@@ -780,6 +981,30 @@ describe('RippleAPI', function () {
'prepare'));
});
it('prepareSettings - invalid', function (done) {
// domain must be a string
const settings = Object.assign({},
requests.prepareSettings.domain,
{domain: 123});
const localInstructions = _.defaults({
signersCount: 4
}, instructions);
try {
this.api.prepareSettings(
address, settings, localInstructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.settings.domain is not of a type(s) string');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareEscrowCreation', function () {
const localInstructions = _.defaults({
maxFee: '0.000012'
@@ -798,6 +1023,23 @@ describe('RippleAPI', function () {
'prepare'));
});
it('prepareEscrowCreation - invalid', function (done) {
const escrow = Object.assign({}, requests.prepareEscrowCreation.full);
delete escrow.amount; // Make invalid
try {
this.api.prepareEscrowCreation(
address, escrow).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, 'instance.escrowCreation requires property "amount"');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareEscrowExecution', function () {
return this.api.prepareEscrowExecution(
address,
@@ -816,18 +1058,34 @@ describe('RippleAPI', function () {
'prepare'));
});
it('prepareEscrowExecution - no condition', function () {
assert.throws(() => {
it('prepareEscrowExecution - no condition', function (done) {
try {
this.api.prepareEscrowExecution(address,
requests.prepareEscrowExecution.noCondition, instructions);
}, /"condition" and "fulfillment" fields on EscrowFinish must only be specified together./);
requests.prepareEscrowExecution.noCondition, instructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, '"condition" and "fulfillment" fields on EscrowFinish must only be specified together.');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareEscrowExecution - no fulfillment', function () {
assert.throws(() => {
it('prepareEscrowExecution - no fulfillment', function (done) {
try {
this.api.prepareEscrowExecution(address,
requests.prepareEscrowExecution.noFulfillment, instructions);
}, /"condition" and "fulfillment" fields on EscrowFinish must only be specified together./);
requests.prepareEscrowExecution.noFulfillment, instructions).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, '"condition" and "fulfillment" fields on EscrowFinish must only be specified together.');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('prepareEscrowCancellation', function () {
@@ -1382,22 +1640,34 @@ describe('RippleAPI', function () {
'prepare'));
});
it('throws on preparePaymentChannelClaim with renew and close', function () {
assert.throws(() => {
it('rejects Promise on preparePaymentChannelClaim with renew and close', function (done) {
try {
this.api.preparePaymentChannelClaim(
address, requests.preparePaymentChannelClaim.full).then(
_.partial(checkResult, responses.preparePaymentChannelClaim.full,
'prepare'));
}, this.api.errors.ValidationError);
address, requests.preparePaymentChannelClaim.full).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, '"renew" and "close" flags on PaymentChannelClaim are mutually exclusive');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('throws on preparePaymentChannelClaim with no signature', function () {
assert.throws(() => {
it('rejects Promise on preparePaymentChannelClaim with no signature', function (done) {
try {
this.api.preparePaymentChannelClaim(
address, requests.preparePaymentChannelClaim.noSignature).then(
_.partial(checkResult, responses.preparePaymentChannelClaim.noSignature,
'prepare'));
}, this.api.errors.ValidationError);
address, requests.preparePaymentChannelClaim.noSignature).then(prepared => {
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
}).catch(err => {
assert.strictEqual(err.name, 'ValidationError');
assert.strictEqual(err.message, '"signature" and "publicKey" fields on PaymentChannelClaim must only be specified together.');
done();
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
} catch (err) {
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
};
});
it('sign', function () {