Update condition and fulfillment for escrow

Calculate escrowFinish fulfillment fee
This commit is contained in:
wilsonianb
2017-03-23 16:40:33 -07:00
parent 15a0ededc8
commit da36457d5c
13 changed files with 76 additions and 35 deletions

View File

@@ -603,8 +603,8 @@ memos | [memos](#transaction-memos) | *Optional* Array of memos to attach to the
{
"owner": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"escrowSequence": 1234,
"condition": "712C36933822AD3A3D136C5DF97AA863B69F9CE88B2D6CE6BDD11BFDE290C19D",
"fulfillment": "this must have 32 characters...."
"condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
"fulfillment": "A0028000"
}
```
@@ -3298,8 +3298,8 @@ const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const escrowExecution = {
"owner": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"escrowSequence": 1234,
"condition": "712C36933822AD3A3D136C5DF97AA863B69F9CE88B2D6CE6BDD11BFDE290C19D",
"fulfillment": "this must have 32 characters...."
"condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
"fulfillment": "A0028000"
};
return api.prepareEscrowExecution(address, escrowExecution).then(prepared =>
{/* ... */});
@@ -3308,9 +3308,9 @@ return api.prepareEscrowExecution(address, escrowExecution).then(prepared =>
```json
{
"txJSON": "{\"Flags\":2147483648,\"TransactionType\":\"EscrowFinish\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Owner\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"OfferSequence\":1234,\"Condition\":\"712C36933822AD3A3D136C5DF97AA863B69F9CE88B2D6CE6BDD11BFDE290C19D\",\"Fulfillment\":\"74686973206D757374206861766520333220636861726163746572732E2E2E2E\",\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
"txJSON": "{\"Flags\":2147483648,\"TransactionType\":\"EscrowFinish\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Owner\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"OfferSequence\":1234,\"Condition\":\"A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100\",\"Fulfillment\":\"A0028000\",\"LastLedgerSequence\":8820051,\"Fee\":\"396\",\"Sequence\":23}",
"instructions": {
"fee": "0.000012",
"fee": "0.000396",
"sequence": 23,
"maxLedgerVersion": 8820051
}

View File

@@ -42,6 +42,8 @@ class Connection extends EventEmitter {
this._retryTimer = null
this._onOpenErrorBound = null
this._onUnexpectedCloseBound = null
this._fee_base = null
this._fee_ref = null
}
_updateLedgerVersions(data) {
@@ -55,6 +57,11 @@ class Connection extends EventEmitter {
}
}
_updateFees(data) {
this._fee_base = Number(data.fee_base)
this._fee_ref = Number(data.fee_ref)
}
// return value is array of arguments to Connection.emit
_parseMessage(message) {
const data = JSON.parse(message)
@@ -66,6 +73,7 @@ class Connection extends EventEmitter {
} else if (isStreamMessageType(data.type)) {
if (data.type === 'ledgerClosed') {
this._updateLedgerVersions(data)
this._updateFees(data)
}
return [data.type, data]
} else if (data.type === undefined && data.error) {
@@ -173,6 +181,7 @@ class Connection extends EventEmitter {
}
this._updateLedgerVersions(data)
this._updateFees(data)
this._rebindOnUnxpectedClose()
this._retry = 0
@@ -354,6 +363,14 @@ class Connection extends EventEmitter {
return this.hasLedgerVersions(ledgerVersion, ledgerVersion)
}
getFeeBase() {
return this._whenReady(Promise.resolve(Number(this._fee_base)))
}
getFeeRef() {
return this._whenReady(Promise.resolve(Number(this._fee_ref)))
}
_send(message) {
if (this._trace) {
this._console.log(message)

View File

@@ -14,8 +14,9 @@
},
"memos": {"$ref": "memos"},
"condition": {
"$ref": "hash256",
"description": "If present, fulfillment is required upon execution."
"type": "string",
"description": "If present, fulfillment is required upon execution.",
"pattern": "^[A-F0-9]{0,256}$"
},
"allowCancelAfter": {
"type": "string",

View File

@@ -14,13 +14,14 @@
"description": "The [account sequence number](#account-sequence-number) of the [Escrow Creation](#escrow-creation) transaction for the escrow to execute."
},
"condition": {
"$ref": "hash256",
"description": "The original `condition` from the escrow creation transaction. This is sha256 hash of `fulfillment` string. It is replicated here so that the relatively expensive hashing operation can be delegated to a server without ledger history and the server with ledger history only has to do a quick comparison of the old condition with the new condition."
"type": "string",
"description": "The original `condition` from the escrow creation transaction. This is sha256 hash of `fulfillment` string. It is replicated here so that the relatively expensive hashing operation can be delegated to a server without ledger history and the server with ledger history only has to do a quick comparison of the old condition with the new condition.",
"pattern": "^[A-F0-9]{0,256}$"
},
"fulfillment": {
"type": "string",
"description": "A value that produces the condition when hashed. It must be 32 charaters long and contain only 8-bit characters.",
"pattern": "^[\\x00-\\xFF]{32}$"
"pattern": "^[A-F0-9]+$"
}
},
"required": ["owner", "escrowSequence"],

View File

@@ -11,7 +11,7 @@ function parseEscrowExecution(tx: Object): Object {
owner: tx.Owner,
escrowSequence: tx.OfferSequence,
condition: tx.Condition,
fulfillment: tx.Fulfillment ? utils.hexToString(tx.Fulfillment) : undefined
fulfillment: tx.Fulfillment
})
}

View File

@@ -3,6 +3,7 @@
const _ = require('lodash')
const utils = require('./utils')
const {validate, iso8601ToRippleTime, toRippledAmount} = utils.common
const ValidationError = utils.common.errors.ValidationError
import type {Instructions, Prepare} from './types.js'
import type {Adjustment, MaxAdjustment, Memo} from '../common/types.js'
@@ -44,9 +45,9 @@ function createEscrowCreationTransaction(account: string,
txJSON.Memos = _.map(payment.memos, utils.convertMemo)
}
if (Boolean(payment.allowCancelAfter) && Boolean(payment.allowExecuteAfter) &&
payment.CancelAfter <= payment.FinishAfter) {
throw new ValidationError('"CancelAfter" must be after "FinishAfter" on'
+ ' EscrowCreate.')
txJSON.CancelAfter <= txJSON.FinishAfter) {
throw new ValidationError('"CancelAfter" must be after "FinishAfter" for'
+ ' EscrowCreate')
}
return txJSON
}

View File

@@ -33,7 +33,7 @@ function createEscrowExecutionTransaction(account: string,
txJSON.Condition = payment.condition
}
if (payment.fulfillment !== undefined) {
txJSON.Fulfillment = utils.convertStringToHex(payment.fulfillment)
txJSON.Fulfillment = payment.fulfillment
}
if (payment.memos !== undefined) {
txJSON.Memos = _.map(payment.memos, utils.convertMemo)

View File

@@ -27,8 +27,8 @@ function setCanonicalFlag(txJSON) {
txJSON.Flags = txJSON.Flags >>> 0
}
function scaleValue(value, multiplier) {
return (new BigNumber(value)).times(multiplier).toString()
function scaleValue(value, multiplier, extra=0) {
return (new BigNumber(value)).times(multiplier).plus(extra).toString()
}
function prepareTransaction(txJSON: Object, api: Object,
@@ -63,15 +63,22 @@ function prepareTransaction(txJSON: Object, api: Object,
}
const cushion = api._feeCushion
return common.serverInfo.getFee(api.connection, cushion).then(fee => {
const feeDrops = common.xrpToDrops(fee)
if (instructions.maxFee !== undefined) {
const maxFeeDrops = common.xrpToDrops(instructions.maxFee)
const normalFee = BigNumber.min(feeDrops, maxFeeDrops).toString()
txJSON.Fee = scaleValue(normalFee, multiplier)
} else {
txJSON.Fee = scaleValue(feeDrops, multiplier)
}
return txJSON
return api.connection.getFeeRef().then(feeRef => {
const extraFee =
(txJSON.TransactionType !== 'EscrowFinish' ||
txJSON.Fulfillment === undefined) ? 0 :
(cushion * feeRef * (32 + Math.floor(
new Buffer(txJSON.Fulfillment, 'hex').length / 16)))
const feeDrops = common.xrpToDrops(fee)
if (instructions.maxFee !== undefined) {
const maxFeeDrops = common.xrpToDrops(instructions.maxFee)
const normalFee = scaleValue(feeDrops, multiplier, extraFee)
txJSON.Fee = BigNumber.min(normalFee, maxFeeDrops).toString();
} else {
txJSON.Fee = scaleValue(feeDrops, multiplier, extraFee)
}
return txJSON
})
})
}

View File

@@ -1136,6 +1136,20 @@ describe('RippleAPI', function() {
}, done);
});
it('getFeeBase', function(done) {
this.api.connection.getFeeBase().then(fee => {
assert.strictEqual(fee, 10);
done();
}, done);
});
it('getFeeRef', function(done) {
this.api.connection.getFeeRef().then(fee => {
assert.strictEqual(fee, 10);
done();
}, done);
});
it('getLedger', function() {
return this.api.getLedger().then(
_.partial(checkResult, responses.getLedger.header, 'getLedger'));

View File

@@ -1,6 +1,6 @@
{
"owner": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"escrowSequence": 1234,
"condition": "712C36933822AD3A3D136C5DF97AA863B69F9CE88B2D6CE6BDD11BFDE290C19D",
"fulfillment": "this must have 32 characters...."
"condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
"fulfillment": "A0028000"
}

View File

@@ -6,8 +6,8 @@
"specification": {
"owner": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"escrowSequence": 5,
"condition": "632F2F3E437AE720C397994A985B5D21FE186DE61523A9CA3E8709CC581671A1",
"fulfillment": "whateverthis bemusthave 32 chars"
"condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
"fulfillment": "A0028000"
},
"outcome": {
"result": "tesSUCCESS",

View File

@@ -1,7 +1,7 @@
{
"txJSON": "{\"Flags\":2147483648,\"TransactionType\":\"EscrowFinish\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Owner\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"OfferSequence\":1234,\"Condition\":\"712C36933822AD3A3D136C5DF97AA863B69F9CE88B2D6CE6BDD11BFDE290C19D\",\"Fulfillment\":\"74686973206D757374206861766520333220636861726163746572732E2E2E2E\",\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}",
"txJSON": "{\"Flags\":2147483648,\"TransactionType\":\"EscrowFinish\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Owner\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"OfferSequence\":1234,\"Condition\":\"A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100\",\"Fulfillment\":\"A0028000\",\"LastLedgerSequence\":8820051,\"Fee\":\"396\",\"Sequence\":23}",
"instructions": {
"fee": "0.000012",
"fee": "0.000396",
"sequence": 23,
"maxLedgerVersion": 8820051
}

View File

@@ -2,13 +2,13 @@
"id": 0,
"result": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Condition": "632F2F3E437AE720C397994A985B5D21FE186DE61523A9CA3E8709CC581671A1",
"Condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
"Fee": "12",
"Flags": 2147483648,
"LastLedgerSequence": 113,
"OfferSequence": 5,
"Owner": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"Fulfillment": "7768617465766572746869732062656D75737468617665203332206368617273",
"Fulfillment": "A0028000",
"Sequence": 6,
"SigningPubKey": "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
"TransactionType": "EscrowFinish",