mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
Add SuspendedPayment{Create,Finish,Cancel}
* Add SusPay core tests
* Rename SusPay -> SuspendedPayment (code review)
* Rename cancelAfter -> allowCancelAfter
* Rename suspendedPayment{Finish,Execution}
This commit is contained in:
@@ -69,6 +69,9 @@ function loadSchemas() {
|
||||
require('./schemas/sign.json'),
|
||||
require('./schemas/signed-value.json'),
|
||||
require('./schemas/submit.json'),
|
||||
require('./schemas/suspended-payment-cancellation.json'),
|
||||
require('./schemas/suspended-payment-execution.json'),
|
||||
require('./schemas/suspended-payment-creation.json'),
|
||||
require('./schemas/timestamp.json'),
|
||||
require('./schemas/transaction-options.json'),
|
||||
require('./schemas/transactions-options.json'),
|
||||
|
||||
17
src/api/common/schemas/suspended-payment-cancellation.json
Normal file
17
src/api/common/schemas/suspended-payment-cancellation.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "suspended-payment-cancellation",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memos": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "memo"
|
||||
}
|
||||
},
|
||||
"owner": {"$ref": "address"},
|
||||
"paymentSequence": {"$ref": "uint32"}
|
||||
},
|
||||
"required": ["owner", "paymentSequence"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
28
src/api/common/schemas/suspended-payment-creation.json
Normal file
28
src/api/common/schemas/suspended-payment-creation.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "suspended-payment-creation",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"$ref": "maxAdjustment"},
|
||||
"destination": {"$ref": "adjustment"},
|
||||
"memos": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "memo"
|
||||
}
|
||||
},
|
||||
"digest": {"$ref": "hash256"},
|
||||
"allowCancelAfter": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "milliseconds since unix epoch"
|
||||
},
|
||||
"allowExecuteAfter": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "milliseconds since unix epoch"
|
||||
}
|
||||
},
|
||||
"required": ["source", "destination"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
20
src/api/common/schemas/suspended-payment-execution.json
Normal file
20
src/api/common/schemas/suspended-payment-execution.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "suspended-payment-execution",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memos": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "memo"
|
||||
}
|
||||
},
|
||||
"owner": {"$ref": "address"},
|
||||
"paymentSequence": {"$ref": "uint32"},
|
||||
"method": {"type": "integer", "minimum": 0, "maximum": 255},
|
||||
"digest": {"$ref": "hash256"},
|
||||
"proof": {"type": "string"}
|
||||
},
|
||||
"required": ["owner", "paymentSequence"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -61,6 +61,12 @@ module.exports = {
|
||||
order: _.partial(schemaValidate, 'order'),
|
||||
orderbook: _.partial(schemaValidate, 'orderbook'),
|
||||
payment: _.partial(schemaValidate, 'payment'),
|
||||
suspendedPaymentCreation:
|
||||
_.partial(schemaValidate, 'suspended-payment-creation'),
|
||||
suspendedPaymentExecution:
|
||||
_.partial(schemaValidate, 'suspended-payment-execution'),
|
||||
suspendedPaymentCancellation:
|
||||
_.partial(schemaValidate, 'suspended-payment-cancellation'),
|
||||
pathfind: _.partial(schemaValidate, 'pathfind'),
|
||||
settings: _.partial(schemaValidate, 'settings'),
|
||||
trustline: _.partial(schemaValidate, 'trustline'),
|
||||
|
||||
@@ -23,6 +23,12 @@ const preparePayment = require('./transaction/payment');
|
||||
const prepareTrustline = require('./transaction/trustline');
|
||||
const prepareOrder = require('./transaction/order');
|
||||
const prepareOrderCancellation = require('./transaction/ordercancellation');
|
||||
const prepareSuspendedPaymentCreation =
|
||||
require('./transaction/suspended-payment-creation');
|
||||
const prepareSuspendedPaymentExecution =
|
||||
require('./transaction/suspended-payment-execution');
|
||||
const prepareSuspendedPaymentCancellation =
|
||||
require('./transaction/suspended-payment-cancellation');
|
||||
const prepareSettings = require('./transaction/settings');
|
||||
const sign = require('./transaction/sign');
|
||||
const submit = require('./transaction/submit');
|
||||
@@ -61,6 +67,9 @@ RippleAPI.prototype = {
|
||||
prepareTrustline,
|
||||
prepareOrder,
|
||||
prepareOrderCancellation,
|
||||
prepareSuspendedPaymentCreation,
|
||||
prepareSuspendedPaymentExecution,
|
||||
prepareSuspendedPaymentCancellation,
|
||||
prepareSettings,
|
||||
sign,
|
||||
submit,
|
||||
|
||||
@@ -18,19 +18,6 @@ function isQualityLimited(tx) {
|
||||
return (tx.Flags & Transaction.flags.Payment.LimitQuality) !== 0;
|
||||
}
|
||||
|
||||
function parsePaymentMemos(tx) {
|
||||
if (!Array.isArray(tx.Memos) || tx.Memos.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return tx.Memos.map((m) => {
|
||||
return utils.removeUndefined({
|
||||
type: m.Memo.parsed_memo_type,
|
||||
format: m.Memo.parsed_memo_format,
|
||||
data: m.Memo.parsed_memo_data
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function removeGenericCounterparty(amount, address) {
|
||||
return amount.counterparty === address ?
|
||||
_.omit(amount, 'counterparty') : amount;
|
||||
@@ -55,7 +42,7 @@ function parsePayment(tx: Object): Object {
|
||||
return utils.removeUndefined({
|
||||
source: utils.removeUndefined(source),
|
||||
destination: utils.removeUndefined(destination),
|
||||
memos: parsePaymentMemos(tx),
|
||||
memos: utils.parseMemos(tx),
|
||||
invoiceID: tx.InvoiceID,
|
||||
paths: tx.Paths ? JSON.stringify(tx.Paths) : undefined,
|
||||
allowPartialPayment: isPartialPayment(tx) || undefined,
|
||||
|
||||
16
src/api/ledger/parse/suspended-payment-cancellation.js
Normal file
16
src/api/ledger/parse/suspended-payment-cancellation.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
|
||||
function parseSuspendedPaymentCancellation(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'SuspendedPaymentCancel');
|
||||
|
||||
return utils.removeUndefined({
|
||||
memos: utils.parseMemos(tx),
|
||||
owner: tx.Owner,
|
||||
paymentSequence: tx.OfferSequence
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseSuspendedPaymentCancellation;
|
||||
39
src/api/ledger/parse/suspended-payment-creation.js
Normal file
39
src/api/ledger/parse/suspended-payment-creation.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
const parseAmount = require('./amount');
|
||||
|
||||
function removeGenericCounterparty(amount, address) {
|
||||
return amount.counterparty === address ?
|
||||
_.omit(amount, 'counterparty') : amount;
|
||||
}
|
||||
|
||||
function parseSuspendedPaymentCreation(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'SuspendedPaymentCreate');
|
||||
|
||||
const source = {
|
||||
address: tx.Account,
|
||||
maxAmount: removeGenericCounterparty(
|
||||
parseAmount(tx.SendMax || tx.Amount), tx.Account),
|
||||
tag: tx.SourceTag
|
||||
};
|
||||
|
||||
const destination = {
|
||||
address: tx.Destination,
|
||||
amount: removeGenericCounterparty(parseAmount(tx.Amount), tx.Destination),
|
||||
tag: tx.DestinationTag
|
||||
};
|
||||
|
||||
return utils.removeUndefined({
|
||||
source: utils.removeUndefined(source),
|
||||
destination: utils.removeUndefined(destination),
|
||||
memos: utils.parseMemos(tx),
|
||||
digest: tx.Digest,
|
||||
allowCancelAfter: tx.CancelAfter,
|
||||
allowExecuteAfter: tx.FinishAfter
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseSuspendedPaymentCreation;
|
||||
25
src/api/ledger/parse/suspended-payment-execution.js
Normal file
25
src/api/ledger/parse/suspended-payment-execution.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
const sjclcodec = require('sjcl-codec');
|
||||
const utils = require('./utils');
|
||||
|
||||
function convertHexToString(hexString) {
|
||||
const bits = sjclcodec.hex.toBits(hexString);
|
||||
return sjclcodec.utf8String.fromBits(bits);
|
||||
}
|
||||
|
||||
function parseSuspendedPaymentExecution(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'SuspendedPaymentFinish');
|
||||
|
||||
return utils.removeUndefined({
|
||||
memos: utils.parseMemos(tx),
|
||||
owner: tx.Owner,
|
||||
paymentSequence: tx.OfferSequence,
|
||||
method: tx.Method,
|
||||
digest: tx.Digest,
|
||||
proof: tx.Proof ? convertHexToString(tx.Proof) : undefined
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseSuspendedPaymentExecution;
|
||||
@@ -7,6 +7,10 @@ const parseTrustline = require('./trustline');
|
||||
const parseOrder = require('./order');
|
||||
const parseOrderCancellation = require('./cancellation');
|
||||
const parseSettings = require('./settings');
|
||||
const parseSuspendedPaymentCreation = require('./suspended-payment-creation');
|
||||
const parseSuspendedPaymentExecution = require('./suspended-payment-execution');
|
||||
const parseSuspendedPaymentCancellation =
|
||||
require('./suspended-payment-cancellation');
|
||||
|
||||
function parseTransactionType(type) {
|
||||
const mapping = {
|
||||
@@ -15,7 +19,10 @@ function parseTransactionType(type) {
|
||||
OfferCreate: 'order',
|
||||
OfferCancel: 'orderCancellation',
|
||||
AccountSet: 'settings',
|
||||
SetRegularKey: 'settings'
|
||||
SetRegularKey: 'settings',
|
||||
SuspendedPaymentCreate: 'suspendedPaymentCreation',
|
||||
SuspendedPaymentFinish: 'suspendedPaymentExecution',
|
||||
SuspendedPaymentCancel: 'suspendedPaymentCancellation'
|
||||
};
|
||||
return mapping[type] || null;
|
||||
}
|
||||
@@ -27,7 +34,10 @@ function parseTransaction(tx: Object): Object {
|
||||
'trustline': parseTrustline,
|
||||
'order': parseOrder,
|
||||
'orderCancellation': parseOrderCancellation,
|
||||
'settings': parseSettings
|
||||
'settings': parseSettings,
|
||||
'suspendedPaymentCreation': parseSuspendedPaymentCreation,
|
||||
'suspendedPaymentExecution': parseSuspendedPaymentExecution,
|
||||
'suspendedPaymentCancellation': parseSuspendedPaymentCancellation
|
||||
};
|
||||
const parser = mapping[type];
|
||||
assert(parser !== undefined, 'Unrecognized transaction type');
|
||||
|
||||
@@ -67,8 +67,22 @@ function parseOutcome(tx: Object): ?Object {
|
||||
};
|
||||
}
|
||||
|
||||
function parseMemos(tx: Object): ?Array<Object> {
|
||||
if (!Array.isArray(tx.Memos) || tx.Memos.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return tx.Memos.map((m) => {
|
||||
return removeUndefined({
|
||||
type: m.Memo.parsed_memo_type,
|
||||
format: m.Memo.parsed_memo_format,
|
||||
data: m.Memo.parsed_memo_data
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseOutcome,
|
||||
parseMemos,
|
||||
removeUndefined,
|
||||
adjustQualityForXRP,
|
||||
dropsToXrp: utils.common.dropsToXrp,
|
||||
|
||||
40
src/api/transaction/suspended-payment-cancellation.js
Normal file
40
src/api/transaction/suspended-payment-cancellation.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const Transaction = utils.common.core.Transaction;
|
||||
|
||||
function createSuspendedPaymentCancellationTransaction(account, payment) {
|
||||
validate.address(account);
|
||||
validate.suspendedPaymentCancellation(payment);
|
||||
|
||||
const transaction = new Transaction();
|
||||
transaction.suspendedPaymentCancel({
|
||||
account: account,
|
||||
owner: payment.owner,
|
||||
paymentSequence: payment.paymentSequence
|
||||
});
|
||||
|
||||
if (payment.memos) {
|
||||
_.forEach(payment.memos, memo =>
|
||||
transaction.addMemo(memo.type, memo.format, memo.data)
|
||||
);
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareSuspendedPaymentCancellationAsync(account, payment,
|
||||
instructions, callback) {
|
||||
const transaction =
|
||||
createSuspendedPaymentCancellationTransaction(account, payment);
|
||||
utils.prepareTransaction(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
function prepareSuspendedPaymentCancellation(account: string, payment: Object,
|
||||
instructions = {}) {
|
||||
return utils.promisify(prepareSuspendedPaymentCancellationAsync)
|
||||
.call(this, account, payment, instructions);
|
||||
}
|
||||
|
||||
module.exports = prepareSuspendedPaymentCancellation;
|
||||
57
src/api/transaction/suspended-payment-creation.js
Normal file
57
src/api/transaction/suspended-payment-creation.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const toRippledAmount = utils.common.toRippledAmount;
|
||||
const Transaction = utils.common.core.Transaction;
|
||||
|
||||
function createSuspendedPaymentCreationTransaction(account, payment) {
|
||||
validate.address(account);
|
||||
validate.suspendedPaymentCreation(payment);
|
||||
|
||||
const transaction = new Transaction();
|
||||
transaction.suspendedPaymentCreate({
|
||||
account: account,
|
||||
destination: payment.destination.address,
|
||||
amount: toRippledAmount(payment.destination.amount)
|
||||
});
|
||||
|
||||
if (payment.digest) {
|
||||
transaction.setDigest(payment.digest);
|
||||
}
|
||||
if (payment.allowCancelAfter) {
|
||||
transaction.setAllowCancelAfter(payment.allowCancelAfter);
|
||||
}
|
||||
if (payment.allowExecuteAfter) {
|
||||
transaction.setAllowExecuteAfter(payment.allowExecuteAfter);
|
||||
}
|
||||
|
||||
if (payment.source.tag) {
|
||||
transaction.sourceTag(payment.source.tag);
|
||||
}
|
||||
if (payment.destination.tag) {
|
||||
transaction.destinationTag(payment.destination.tag);
|
||||
}
|
||||
if (payment.memos) {
|
||||
_.forEach(payment.memos, memo =>
|
||||
transaction.addMemo(memo.type, memo.format, memo.data)
|
||||
);
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareSuspendedPaymentCreationAsync(account, payment, instructions,
|
||||
callback) {
|
||||
const transaction =
|
||||
createSuspendedPaymentCreationTransaction(account, payment);
|
||||
utils.prepareTransaction(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
function prepareSuspendedPaymentCreation(account: string, payment: Object,
|
||||
instructions = {}) {
|
||||
return utils.promisify(prepareSuspendedPaymentCreationAsync)
|
||||
.call(this, account, payment, instructions);
|
||||
}
|
||||
|
||||
module.exports = prepareSuspendedPaymentCreation;
|
||||
50
src/api/transaction/suspended-payment-execution.js
Normal file
50
src/api/transaction/suspended-payment-execution.js
Normal file
@@ -0,0 +1,50 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const Transaction = utils.common.core.Transaction;
|
||||
|
||||
function createSuspendedPaymentExecutionTransaction(account, payment) {
|
||||
validate.address(account);
|
||||
validate.suspendedPaymentExecution(payment);
|
||||
|
||||
const transaction = new Transaction();
|
||||
transaction.suspendedPaymentFinish({
|
||||
account: account,
|
||||
owner: payment.owner,
|
||||
paymentSequence: payment.paymentSequence
|
||||
});
|
||||
|
||||
if (payment.method) {
|
||||
transaction.setMethod(payment.method);
|
||||
}
|
||||
if (payment.digest) {
|
||||
transaction.setDigest(payment.digest);
|
||||
}
|
||||
if (payment.proof) {
|
||||
transaction.setProof(payment.proof);
|
||||
}
|
||||
|
||||
if (payment.memos) {
|
||||
_.forEach(payment.memos, memo =>
|
||||
transaction.addMemo(memo.type, memo.format, memo.data)
|
||||
);
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareSuspendedPaymentExecutionAsync(account, payment, instructions,
|
||||
callback) {
|
||||
const transaction =
|
||||
createSuspendedPaymentExecutionTransaction(account, payment);
|
||||
utils.prepareTransaction(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
function prepareSuspendedPaymentExecution(account: string, payment: Object,
|
||||
instructions = {}) {
|
||||
return utils.promisify(prepareSuspendedPaymentExecutionAsync)
|
||||
.call(this, account, payment, instructions);
|
||||
}
|
||||
|
||||
module.exports = prepareSuspendedPaymentExecution;
|
||||
@@ -92,6 +92,8 @@ const FIELDS_MAP = exports.fields = {
|
||||
33: 'SetFlag',
|
||||
34: 'ClearFlag',
|
||||
35: 'SignerQuorum',
|
||||
36: 'CancelAfter',
|
||||
37: 'FinishAfter',
|
||||
38: 'SignerListID'
|
||||
},
|
||||
3: { // Int64
|
||||
@@ -121,7 +123,8 @@ const FIELDS_MAP = exports.fields = {
|
||||
17: 'InvoiceID',
|
||||
18: 'Nickname',
|
||||
19: 'Amendment',
|
||||
20: 'TicketID'
|
||||
20: 'TicketID',
|
||||
21: 'Digest'
|
||||
},
|
||||
6: { // Amount
|
||||
1: 'Amount',
|
||||
@@ -151,7 +154,8 @@ const FIELDS_MAP = exports.fields = {
|
||||
11: 'CreateCode',
|
||||
12: 'MemoType',
|
||||
13: 'MemoData',
|
||||
14: 'MemoFormat'
|
||||
14: 'MemoFormat',
|
||||
17: 'Proof'
|
||||
},
|
||||
8: { // Account
|
||||
1: 'Account',
|
||||
@@ -190,7 +194,7 @@ const FIELDS_MAP = exports.fields = {
|
||||
// Uncommon types
|
||||
16: { // Int8
|
||||
1: 'CloseResolution',
|
||||
2: 'TemplateEntryType',
|
||||
2: 'Method',
|
||||
3: 'TransactionResult'
|
||||
},
|
||||
17: { // Hash160
|
||||
@@ -217,9 +221,9 @@ Object.keys(FIELDS_MAP).forEach(function(k1) {
|
||||
});
|
||||
});
|
||||
|
||||
const REQUIRED = exports.REQUIRED = 0,
|
||||
OPTIONAL = exports.OPTIONAL = 1,
|
||||
DEFAULT = exports.DEFAULT = 2;
|
||||
const REQUIRED = exports.REQUIRED = 0;
|
||||
const OPTIONAL = exports.OPTIONAL = 1;
|
||||
const DEFAULT = exports.DEFAULT = 2;
|
||||
|
||||
const base = [
|
||||
[ 'TransactionType' , REQUIRED ],
|
||||
@@ -308,6 +312,25 @@ exports.tx = {
|
||||
SignerListSet: [12].concat(base, [
|
||||
['SignerQuorum', REQUIRED],
|
||||
['SignerEntries', OPTIONAL]
|
||||
]),
|
||||
SuspendedPaymentCreate: [1].concat(base, [
|
||||
[ 'Destination' , REQUIRED ],
|
||||
[ 'Amount' , REQUIRED ],
|
||||
[ 'Digest' , OPTIONAL ],
|
||||
[ 'CancelAfter' , OPTIONAL ],
|
||||
[ 'FinishAfter' , OPTIONAL ],
|
||||
[ 'DestinationTag' , OPTIONAL ]
|
||||
]),
|
||||
SuspendedPaymentFinish: [2].concat(base, [
|
||||
[ 'Owner' , REQUIRED ],
|
||||
[ 'OfferSequence' , REQUIRED ],
|
||||
[ 'Method' , OPTIONAL ],
|
||||
[ 'Digest' , OPTIONAL ],
|
||||
[ 'Proof' , OPTIONAL ]
|
||||
]),
|
||||
SuspendedPaymentCancel: [4].concat(base, [
|
||||
[ 'Owner' , REQUIRED ],
|
||||
[ 'OfferSequence' , REQUIRED ]
|
||||
])
|
||||
};
|
||||
|
||||
|
||||
@@ -2276,7 +2276,10 @@ Remote.prototype.createTransaction = function(type, options = {}) {
|
||||
OfferCreate: transaction.offerCreate,
|
||||
OfferCancel: transaction.offerCancel,
|
||||
SetRegularKey: transaction.setRegularKey,
|
||||
SignerListSet: transaction.setSignerList
|
||||
SignerListSet: transaction.setSignerList,
|
||||
SuspendedPaymentCreate: transaction.suspendedPaymentCreate,
|
||||
SuspendedPaymentFinish: transaction.suspendedPaymentFinish,
|
||||
SuspendedPaymentCancel: transaction.suspendedPaymentCancel
|
||||
};
|
||||
|
||||
const transactionConstructor = constructorMap[type];
|
||||
|
||||
@@ -808,6 +808,11 @@ Transaction.prototype.setFlags = function(flags) {
|
||||
return this;
|
||||
};
|
||||
|
||||
function convertStringToHex(string) {
|
||||
const utf8String = sjclcodec.utf8String.toBits(string);
|
||||
return sjclcodec.hex.fromBits(utf8String).toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Memo to transaction.
|
||||
*
|
||||
@@ -834,11 +839,6 @@ Transaction.prototype.addMemo = function(options_) {
|
||||
};
|
||||
}
|
||||
|
||||
function convertStringToHex(string) {
|
||||
const utf8String = sjclcodec.utf8String.toBits(string);
|
||||
return sjclcodec.hex.fromBits(utf8String).toUpperCase();
|
||||
}
|
||||
|
||||
const memo = {};
|
||||
const memoRegex = Transaction.MEMO_REGEX;
|
||||
let memoType = options.memoType;
|
||||
@@ -1501,6 +1501,110 @@ Transaction.prototype.summary = function() {
|
||||
return txSummary;
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a 'SuspendedPaymentCreate' transaction
|
||||
*
|
||||
* Relevant setters:
|
||||
* - setSourceTag()
|
||||
* - setFlags()
|
||||
* - setDigest()
|
||||
* - setAllowCancelAfter()
|
||||
* - setAllowExecuteAfter()
|
||||
*
|
||||
* @param {String} options.account source account
|
||||
* @param {String} options.destination account
|
||||
* @param {Amount} options.amount payment amount
|
||||
*/
|
||||
|
||||
Transaction.prototype.suspendedPaymentCreate = function(options) {
|
||||
this.setType('SuspendedPaymentCreate');
|
||||
this.setAccount(options.account);
|
||||
this.setDestination(options.destination);
|
||||
this.setAmount(options.amount);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a 'SuspendedPaymentFinish' transaction
|
||||
*
|
||||
* Relevant setters:
|
||||
* - setSourceTag()
|
||||
* - setFlags()
|
||||
* - setOwner()
|
||||
* - setOfferSequence()
|
||||
* - setMethod()
|
||||
* - setDigest()
|
||||
* - setProof()
|
||||
*
|
||||
* @param {String} options.account source account
|
||||
* @param {String} options.owner SuspendedPaymentCreate's Account
|
||||
* @param {Integer} options.paymentSequence SuspendedPaymentCreate's Sequence
|
||||
*/
|
||||
|
||||
Transaction.prototype.suspendedPaymentFinish = function(options) {
|
||||
this.setType('SuspendedPaymentFinish');
|
||||
this.setAccount(options.account);
|
||||
this.setOwner(options.owner);
|
||||
this.setOfferSequence(options.paymentSequence);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a 'SuspendedPaymentCancel' transaction
|
||||
*
|
||||
* Relevant setters:
|
||||
* - setSourceTag()
|
||||
* - setFlags()
|
||||
* - setOwner()
|
||||
* - setOfferSequence()
|
||||
*
|
||||
* @param {String} options.account source account
|
||||
* @param {String} options.owner SuspendedPaymentCreate's Account
|
||||
* @param {Integer} options.paymentSequence SuspendedPaymentCreate's Sequence
|
||||
*/
|
||||
|
||||
Transaction.prototype.suspendedPaymentCancel = function(options) {
|
||||
this.setType('SuspendedPaymentCancel');
|
||||
this.setAccount(options.account);
|
||||
this.setOwner(options.owner);
|
||||
this.setOfferSequence(options.paymentSequence);
|
||||
return this;
|
||||
};
|
||||
|
||||
Transaction.prototype.setDigest = function(digest) {
|
||||
return this._setHash256('Digest', digest);
|
||||
};
|
||||
|
||||
Transaction.prototype.setAllowCancelAfter = function(after) {
|
||||
return this._setUInt32('CancelAfter', utils.time.toRipple(after));
|
||||
};
|
||||
|
||||
Transaction.prototype.setAllowExecuteAfter = function(after) {
|
||||
return this._setUInt32('FinishAfter', utils.time.toRipple(after));
|
||||
};
|
||||
|
||||
Transaction.prototype.setOwner = function(owner) {
|
||||
return this._setAccount('Owner', owner);
|
||||
};
|
||||
|
||||
Transaction.prototype.setMethod = function(method) {
|
||||
return this._setUInt8('Method', method);
|
||||
};
|
||||
|
||||
Transaction.prototype.setProof = function(proof) {
|
||||
this.tx_json.Proof = convertStringToHex(proof);
|
||||
return this;
|
||||
};
|
||||
|
||||
Transaction.prototype._setUInt8 = function(name, value) {
|
||||
const isValidUInt8 = typeof value === 'number' && value >= 0 && value < 256;
|
||||
if (!isValidUInt8) {
|
||||
throw new Error(name + ' must be a valid UInt8');
|
||||
}
|
||||
this.tx_json[name] = value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Transaction.prototype.setSigners = function(signers) {
|
||||
if (_.isArray(signers)) {
|
||||
this.tx_json.Signers = signers;
|
||||
|
||||
@@ -143,6 +143,31 @@ describe('RippleAPI', function() {
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSuspendedPaymentCreation', function() {
|
||||
const localInstructions = _.defaults({
|
||||
maxFee: '0.000012'
|
||||
}, instructions);
|
||||
return this.api.prepareSuspendedPaymentCreation(
|
||||
address, requests.prepareSuspendedPaymentCreation,
|
||||
localInstructions).then(
|
||||
_.partial(checkResult, responses.prepareSuspendedPaymentCreation,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSuspendedPaymentExecution', function() {
|
||||
return this.api.prepareSuspendedPaymentExecution(
|
||||
address, requests.prepareSuspendedPaymentExecution, instructions).then(
|
||||
_.partial(checkResult, responses.prepareSuspendedPaymentExecution,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSuspendedPaymentCancellation', function() {
|
||||
return this.api.prepareSuspendedPaymentCancellation(
|
||||
address, requests.prepareSuspendedPaymentCancellation, instructions).then(
|
||||
_.partial(checkResult, responses.prepareSuspendedPaymentCancellation,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('sign', function() {
|
||||
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV';
|
||||
const result = this.api.sign(requests.sign.txJSON, secret);
|
||||
|
||||
6
test/fixtures/api/requests/index.js
vendored
6
test/fixtures/api/requests/index.js
vendored
@@ -7,6 +7,12 @@ module.exports = {
|
||||
preparePaymentAllOptions: require('./prepare-payment-all-options'),
|
||||
preparePaymentNoCounterparty: require('./prepare-payment-no-counterparty'),
|
||||
prepareSettings: require('./prepare-settings'),
|
||||
prepareSuspendedPaymentCreation:
|
||||
require('./prepare-suspended-payment-creation'),
|
||||
prepareSuspendedPaymentExecution:
|
||||
require('./prepare-suspended-payment-execution'),
|
||||
prepareSuspendedPaymentCancellation:
|
||||
require('./prepare-suspended-payment-cancellation'),
|
||||
prepareTrustline: {
|
||||
simple: require('./prepare-trustline-simple'),
|
||||
complex: require('./prepare-trustline')
|
||||
|
||||
4
test/fixtures/api/requests/prepare-suspended-payment-cancellation.json
vendored
Normal file
4
test/fixtures/api/requests/prepare-suspended-payment-cancellation.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"owner": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"paymentSequence": 1234
|
||||
}
|
||||
19
test/fixtures/api/requests/prepare-suspended-payment-creation.json
vendored
Normal file
19
test/fixtures/api/requests/prepare-suspended-payment-creation.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"source": {
|
||||
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"maxAmount": {
|
||||
"value": "0.01",
|
||||
"currency": "USD",
|
||||
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
|
||||
}
|
||||
},
|
||||
"destination": {
|
||||
"address": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
|
||||
"amount": {
|
||||
"value": "0.01",
|
||||
"currency": "USD",
|
||||
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
|
||||
}
|
||||
},
|
||||
"allowCancelAfter": 1440694329002
|
||||
}
|
||||
7
test/fixtures/api/requests/prepare-suspended-payment-execution.json
vendored
Normal file
7
test/fixtures/api/requests/prepare-suspended-payment-execution.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"owner": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"paymentSequence": 1234,
|
||||
"method": 1,
|
||||
"digest": "8F434346648F6B96DF89DDA901C5176B10A6D83961DD3C1AC88B59B2DC327AA4",
|
||||
"proof": "whatever"
|
||||
}
|
||||
6
test/fixtures/api/responses/index.js
vendored
6
test/fixtures/api/responses/index.js
vendored
@@ -47,6 +47,12 @@ module.exports = {
|
||||
setTransferRate: require('./prepare-settings-set-transfer-rate.json'),
|
||||
fieldClear: require('./prepare-settings-field-clear.json')
|
||||
},
|
||||
prepareSuspendedPaymentCreation:
|
||||
require('./prepare-suspended-payment-creation'),
|
||||
prepareSuspendedPaymentExecution:
|
||||
require('./prepare-suspended-payment-execution'),
|
||||
prepareSuspendedPaymentCancellation:
|
||||
require('./prepare-suspended-payment-cancellation'),
|
||||
prepareTrustline: {
|
||||
simple: require('./prepare-trustline-simple.json'),
|
||||
complex: require('./prepare-trustline.json')
|
||||
|
||||
8
test/fixtures/api/responses/prepare-suspended-payment-cancellation.json
vendored
Normal file
8
test/fixtures/api/responses/prepare-suspended-payment-cancellation.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"txJSON": "{\"Flags\":0,\"TransactionType\":\"SuspendedPaymentCancel\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Owner\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"OfferSequence\":1234,\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"instructions": {
|
||||
"fee": "12",
|
||||
"sequence": 23,
|
||||
"maxLedgerVersion": 8820051
|
||||
}
|
||||
}
|
||||
8
test/fixtures/api/responses/prepare-suspended-payment-creation.json
vendored
Normal file
8
test/fixtures/api/responses/prepare-suspended-payment-creation.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"txJSON": "{\"Flags\":0,\"TransactionType\":\"SuspendedPaymentCreate\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"Amount\":{\"value\":\"0.01\",\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\"},\"CancelAfter\":494009529,\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"instructions": {
|
||||
"fee": "12",
|
||||
"sequence": 23,
|
||||
"maxLedgerVersion": 8820051
|
||||
}
|
||||
}
|
||||
8
test/fixtures/api/responses/prepare-suspended-payment-execution.json
vendored
Normal file
8
test/fixtures/api/responses/prepare-suspended-payment-execution.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"txJSON": "{\"Flags\":0,\"TransactionType\":\"SuspendedPaymentFinish\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Owner\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"OfferSequence\":1234,\"Method\":1,\"Digest\":\"8F434346648F6B96DF89DDA901C5176B10A6D83961DD3C1AC88B59B2DC327AA4\",\"Proof\":\"7768617465766572\",\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
|
||||
"instructions": {
|
||||
"fee": "12",
|
||||
"sequence": 23,
|
||||
"maxLedgerVersion": 8820051
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable no-new, max-len, no-comma-dangle, indent */
|
||||
/* eslint-disable no-new, max-len, no-comma-dangle, indent, max-nested-callbacks */
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -14,7 +14,9 @@ const Amount = require('ripple-lib').Amount;
|
||||
const PathFind = require('ripple-lib')._test.PathFind;
|
||||
const Log = require('ripple-lib')._test.Log;
|
||||
|
||||
let options, remote, callback;
|
||||
let options;
|
||||
let remote;
|
||||
let callback;
|
||||
|
||||
const ADDRESS = 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS';
|
||||
const LEDGER_INDEX = 9592219;
|
||||
@@ -2095,4 +2097,50 @@ describe('Remote', function() {
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('Construct SuspendedPaymentCreate transaction', function() {
|
||||
const tx = remote.createTransaction('SuspendedPaymentCreate', {
|
||||
account: TX_JSON.Account,
|
||||
destination: TX_JSON.Destination,
|
||||
amount: TX_JSON.Amount
|
||||
});
|
||||
|
||||
assert.deepEqual(tx.tx_json, {
|
||||
Flags: 0,
|
||||
TransactionType: 'SuspendedPaymentCreate',
|
||||
Account: TX_JSON.Account,
|
||||
Destination: TX_JSON.Destination,
|
||||
Amount: TX_JSON.Amount
|
||||
});
|
||||
});
|
||||
it('Construct SuspendedPaymentFinish transaction', function() {
|
||||
const tx = remote.createTransaction('SuspendedPaymentFinish', {
|
||||
account: TX_JSON.Account,
|
||||
owner: TX_JSON.Account,
|
||||
paymentSequence: 1234
|
||||
});
|
||||
|
||||
assert.deepEqual(tx.tx_json, {
|
||||
Flags: 0,
|
||||
TransactionType: 'SuspendedPaymentFinish',
|
||||
Account: TX_JSON.Account,
|
||||
Owner: TX_JSON.Account,
|
||||
OfferSequence: 1234
|
||||
});
|
||||
});
|
||||
it('Construct SuspendedPaymentCancel transaction', function() {
|
||||
const tx = remote.createTransaction('SuspendedPaymentCancel', {
|
||||
account: TX_JSON.Account,
|
||||
owner: TX_JSON.Account,
|
||||
paymentSequence: 1234
|
||||
});
|
||||
|
||||
assert.deepEqual(tx.tx_json, {
|
||||
Flags: 0,
|
||||
TransactionType: 'SuspendedPaymentCancel',
|
||||
Account: TX_JSON.Account,
|
||||
Owner: TX_JSON.Account,
|
||||
OfferSequence: 1234
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable max-len */
|
||||
/* eslint-disable max-len, max-nested-callbacks */
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -2182,4 +2182,116 @@ describe('Transaction', function() {
|
||||
{Signer: s1}
|
||||
]);
|
||||
});
|
||||
|
||||
it('Construct SuspendedPaymentCreate transaction', function() {
|
||||
const transaction = new Transaction().suspendedPaymentCreate({
|
||||
account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
destination: 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe',
|
||||
amount: '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'
|
||||
});
|
||||
|
||||
assert(transaction instanceof Transaction);
|
||||
assert.deepEqual(transaction.tx_json, {
|
||||
Flags: 0,
|
||||
TransactionType: 'SuspendedPaymentCreate',
|
||||
Account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
Destination: 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe',
|
||||
Amount: {
|
||||
value: '1',
|
||||
currency: 'USD',
|
||||
issuer: 'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('Set Digest', function() {
|
||||
const transaction = new Transaction();
|
||||
assert.strictEqual(transaction.tx_json.Digest, undefined);
|
||||
transaction.setType('SuspendedPaymentCreate');
|
||||
assert.throws(function() {
|
||||
transaction.setDigest('foo');
|
||||
}, /Error: Digest must be a valid Hash256/);
|
||||
|
||||
const hash = '8F434346648F6B96DF89DDA901C5176B10A6D83961DD3C1AC88B59B2DC327AA4';
|
||||
transaction.setDigest(hash);
|
||||
assert.strictEqual(transaction.tx_json.Digest, hash);
|
||||
});
|
||||
|
||||
it('Set CancelAfter', function() {
|
||||
const transaction = new Transaction();
|
||||
assert.strictEqual(transaction.tx_json.CancelAfter, undefined);
|
||||
transaction.setType('SuspendedPaymentCreate');
|
||||
assert.throws(function() {
|
||||
transaction.setAllowCancelAfter('foo');
|
||||
}, /Error: CancelAfter must be a valid UInt32/);
|
||||
|
||||
transaction.setAllowCancelAfter(1441043377523);
|
||||
assert.strictEqual(transaction.tx_json.CancelAfter, 494358578);
|
||||
});
|
||||
|
||||
it('Set FinishAfter', function() {
|
||||
const transaction = new Transaction();
|
||||
assert.strictEqual(transaction.tx_json.FinishAfter, undefined);
|
||||
transaction.setType('SuspendedPaymentCreate');
|
||||
assert.throws(function() {
|
||||
transaction.setAllowExecuteAfter('foo');
|
||||
}, /Error: FinishAfter must be a valid UInt32/);
|
||||
|
||||
transaction.setAllowExecuteAfter(1441043377523);
|
||||
assert.strictEqual(transaction.tx_json.FinishAfter, 494358578);
|
||||
});
|
||||
|
||||
it('Construct SuspendedPaymentFinish transaction', function() {
|
||||
const transaction = new Transaction().suspendedPaymentFinish({
|
||||
account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
owner: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
paymentSequence: 1234
|
||||
});
|
||||
|
||||
assert(transaction instanceof Transaction);
|
||||
assert.deepEqual(transaction.tx_json, {
|
||||
Flags: 0,
|
||||
TransactionType: 'SuspendedPaymentFinish',
|
||||
Account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
Owner: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
OfferSequence: 1234
|
||||
});
|
||||
});
|
||||
|
||||
it('Set Method', function() {
|
||||
const transaction = new Transaction();
|
||||
assert.strictEqual(transaction.tx_json.Method, undefined);
|
||||
transaction.setType('SuspendedPaymentFinish');
|
||||
assert.throws(function() {
|
||||
transaction.setMethod('foo');
|
||||
}, /Error: Method must be a valid UInt8/);
|
||||
|
||||
transaction.setMethod(1);
|
||||
assert.strictEqual(transaction.tx_json.Method, 1);
|
||||
});
|
||||
|
||||
it('Set Proof', function() {
|
||||
const transaction = new Transaction();
|
||||
assert.strictEqual(transaction.tx_json.Proof, undefined);
|
||||
transaction.setType('SuspendedPaymentFinish');
|
||||
transaction.setProof('foo');
|
||||
assert.strictEqual(transaction.tx_json.Proof, '666F6F');
|
||||
});
|
||||
|
||||
it('Construct SuspendedPaymentCancel transaction', function() {
|
||||
const transaction = new Transaction().suspendedPaymentCancel({
|
||||
account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
owner: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
paymentSequence: 1234
|
||||
});
|
||||
|
||||
assert(transaction instanceof Transaction);
|
||||
assert.deepEqual(transaction.tx_json, {
|
||||
Flags: 0,
|
||||
TransactionType: 'SuspendedPaymentCancel',
|
||||
Account: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
Owner: 'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
|
||||
OfferSequence: 1234
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user