From 6cc8c5a0f46e05bda6eb7d7a29a9eb096f0e72d1 Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Mon, 2 Nov 2015 10:54:22 -0800 Subject: [PATCH] BREAKING CHANGE: Specify ledger close time and suspended payment timestamps in ISO 8601 format --- src/common/index.js | 4 ++-- .../input/suspended-payment-creation.json | 12 ++---------- src/common/schemas/output/get-ledger.json | 4 ++-- src/common/utils.js | 19 ++++++++++++------- src/ledger/parse/ledger.js | 6 +++--- .../parse/suspended-payment-creation.js | 4 ++-- src/ledger/parse/utils.js | 9 ++++----- src/offline/ledgerhash.js | 4 ++-- src/server/server.js | 6 +----- src/transaction/order.js | 5 ++--- src/transaction/suspended-payment-creation.js | 10 +++++----- .../requests/compute-ledger-hash.json | 5 ++--- .../prepare-suspended-payment-creation.json | 2 +- test/fixtures/responses/get-ledger-full.json | 4 ++-- .../get-ledger-with-settings-tx.json | 4 ++-- test/fixtures/responses/get-ledger.json | 4 ++-- .../prepare-suspended-payment-creation.json | 2 +- 17 files changed, 47 insertions(+), 57 deletions(-) diff --git a/src/common/index.js b/src/common/index.js index aa77581a..815d3b6e 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -16,6 +16,6 @@ module.exports = { removeUndefined: utils.removeUndefined, convertKeysFromSnakeCaseToCamelCase: utils.convertKeysFromSnakeCaseToCamelCase, - rippleToUnixTimestamp: utils.rippleToUnixTimestamp, - unixToRippleTimestamp: utils.unixToRippleTimestamp + iso8601ToRippleTime: utils.iso8601ToRippleTime, + rippleTimeToISO8601: utils.rippleTimeToISO8601 }; diff --git a/src/common/schemas/input/suspended-payment-creation.json b/src/common/schemas/input/suspended-payment-creation.json index 2dbf667d..e575653d 100644 --- a/src/common/schemas/input/suspended-payment-creation.json +++ b/src/common/schemas/input/suspended-payment-creation.json @@ -12,16 +12,8 @@ } }, "digest": {"$ref": "hash256"}, - "allowCancelAfter": { - "type": "integer", - "minimum": 0, - "description": "milliseconds since unix epoch" - }, - "allowExecuteAfter": { - "type": "integer", - "minimum": 0, - "description": "milliseconds since unix epoch" - } + "allowCancelAfter": {"type": "string", "format": "date-time"}, + "allowExecuteAfter": {"type": "string", "format": "date-time"} }, "required": ["source", "destination"], "additionalProperties": false diff --git a/src/common/schemas/output/get-ledger.json b/src/common/schemas/output/get-ledger.json index d280c5be..0beb6f8c 100644 --- a/src/common/schemas/output/get-ledger.json +++ b/src/common/schemas/output/get-ledger.json @@ -6,13 +6,13 @@ "accepted": {"type": "boolean"}, "closed": {"type": "boolean"}, "stateHash": {"$ref": "hash256"}, - "closeTime": {"type": "integer", "minimum": 0}, + "closeTime": {"type": "string", "format": "date-time"}, "closeTimeResolution": {"type": "integer", "minimum": 1}, "closeFlags": {"type": "integer", "minimum": 0}, "ledgerHash": {"$ref": "hash256"}, "ledgerVersion": {"$ref": "ledgerVersion"}, "parentLedgerHash": {"$ref": "hash256"}, - "parentCloseTime": {"type": "integer", "minimum": 0}, + "parentCloseTime": {"type": "string", "format": "date-time"}, "totalDrops": {"$ref": "value"}, "transactionHash": {"$ref": "hash256"}, "transactions": {"type": "array", "items": {"type": "object"}}, diff --git a/src/common/utils.js b/src/common/utils.js index 6ee5e70b..0ce92cd3 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -75,11 +75,16 @@ function rippleToUnixTimestamp(rpepoch: number): number { * @param {Number|Date} timestamp (ms since unix epoch) * @return {Number} seconds since ripple epoch ( 1/1/2000 GMT) */ -function unixToRippleTimestamp(timestamp: number | Date): number { - const timestamp_ = timestamp instanceof Date ? - timestamp.getTime() : - timestamp; - return Math.round(timestamp_ / 1000) - 0x386D4380; +function unixToRippleTimestamp(timestamp: number): number { + return Math.round(timestamp / 1000) - 0x386D4380; +} + +function rippleTimeToISO8601(rippleTime: number): string { + return new Date(rippleToUnixTimestamp(rippleTime)).toISOString(); +} + +function iso8601ToRippleTime(iso8601: string): number { + return unixToRippleTimestamp(Date.parse(iso8601)); } module.exports = { @@ -90,6 +95,6 @@ module.exports = { generateAddressAPI, convertKeysFromSnakeCaseToCamelCase, removeUndefined, - rippleToUnixTimestamp, - unixToRippleTimestamp + rippleTimeToISO8601, + iso8601ToRippleTime }; diff --git a/src/ledger/parse/ledger.js b/src/ledger/parse/ledger.js index d654ffc4..7279c150 100644 --- a/src/ledger/parse/ledger.js +++ b/src/ledger/parse/ledger.js @@ -1,7 +1,7 @@ /* @flow */ 'use strict'; const _ = require('lodash'); -const removeUndefined = require('./utils').removeUndefined; +const {removeUndefined, rippleTimeToISO8601} = require('./utils'); const parseTransaction = require('./transaction'); import type {GetLedger} from '../types.js'; @@ -39,13 +39,13 @@ function parseLedger(ledger: Object): GetLedger { accepted: ledger.accepted, closed: ledger.closed, stateHash: ledger.account_hash, - closeTime: ledger.close_time, + closeTime: rippleTimeToISO8601(ledger.close_time), closeTimeResolution: ledger.close_time_resolution, closeFlags: ledger.close_flags, ledgerHash: ledger.hash || ledger.ledger_hash, ledgerVersion: parseInt(ledger.ledger_index || ledger.seqNum, 10), parentLedgerHash: ledger.parent_hash, - parentCloseTime: ledger.parent_close_time, + parentCloseTime: rippleTimeToISO8601(ledger.parent_close_time), totalDrops: ledger.total_coins || ledger.totalCoins, transactionHash: ledger.transaction_hash }, diff --git a/src/ledger/parse/suspended-payment-creation.js b/src/ledger/parse/suspended-payment-creation.js index 7b91b265..842fb239 100644 --- a/src/ledger/parse/suspended-payment-creation.js +++ b/src/ledger/parse/suspended-payment-creation.js @@ -31,8 +31,8 @@ function parseSuspendedPaymentCreation(tx: Object): Object { destination: utils.removeUndefined(destination), memos: utils.parseMemos(tx), digest: tx.Digest, - allowCancelAfter: tx.CancelAfter, - allowExecuteAfter: tx.FinishAfter + allowCancelAfter: utils.parseTimestamp(tx.CancelAfter), + allowExecuteAfter: utils.parseTimestamp(tx.FinishAfter) }); } diff --git a/src/ledger/parse/utils.js b/src/ledger/parse/utils.js index dcf70853..7b03b288 100644 --- a/src/ledger/parse/utils.js +++ b/src/ledger/parse/utils.js @@ -3,7 +3,6 @@ const _ = require('lodash'); const transactionParser = require('ripple-lib-transactionparser'); const utils = require('../utils'); -const rippleToUnixTimestamp = utils.common.rippleToUnixTimestamp; const BigNumber = require('bignumber.js'); function adjustQualityForXRP( @@ -18,9 +17,8 @@ function adjustQualityForXRP( (new BigNumber(quality)).shift(shift).toString(); } -function parseTimestamp(date: number): string | void { - return date ? (new Date(rippleToUnixTimestamp(date))).toISOString() - : undefined; +function parseTimestamp(rippleTime: number): string | void { + return rippleTime ? utils.common.rippleTimeToISO8601(rippleTime) : undefined; } function removeEmptyCounterparty(amount) { @@ -90,5 +88,6 @@ module.exports = { dropsToXrp: utils.common.dropsToXrp, constants: utils.common.constants, txFlags: utils.common.txFlags, - removeUndefined: utils.common.removeUndefined + removeUndefined: utils.common.removeUndefined, + rippleTimeToISO8601: utils.common.rippleTimeToISO8601 }; diff --git a/src/offline/ledgerhash.js b/src/offline/ledgerhash.js index 69b60365..039de60e 100644 --- a/src/offline/ledgerhash.js +++ b/src/offline/ledgerhash.js @@ -9,7 +9,7 @@ function convertLedgerHeader(header) { accepted: header.accepted, closed: header.closed, account_hash: header.stateHash, - close_time: header.closeTime, + close_time: common.iso8601ToRippleTime(header.closeTime), close_time_resolution: header.closeTimeResolution, close_flags: header.closeFlags, hash: header.ledgerHash, @@ -17,7 +17,7 @@ function convertLedgerHeader(header) { ledger_index: header.ledgerVersion.toString(), seqNum: header.ledgerVersion.toString(), parent_hash: header.parentLedgerHash, - parent_close_time: header.parentCloseTime, + parent_close_time: common.iso8601ToRippleTime(header.parentCloseTime), total_coins: header.totalDrops, totalCoins: header.totalDrops, transaction_hash: header.transactionHash diff --git a/src/server/server.js b/src/server/server.js index bf20ff49..0b30a66f 100644 --- a/src/server/server.js +++ b/src/server/server.js @@ -28,17 +28,13 @@ function getFee(): Promise { return common.serverInfo.getFee(this.connection, cushion); } -function rippleTimeToISO8601(rippleTime: string): string { - return new Date(common.rippleToUnixTimestamp(rippleTime)).toISOString(); -} - function formatLedgerClose(ledgerClose: Object): Object { return { feeBase: ledgerClose.fee_base, feeReference: ledgerClose.fee_ref, ledgerHash: ledgerClose.ledger_hash, ledgerVersion: ledgerClose.ledger_index, - ledgerTimestamp: rippleTimeToISO8601(ledgerClose.ledger_time), + ledgerTimestamp: common.rippleTimeToISO8601(ledgerClose.ledger_time), reserveBase: ledgerClose.reserve_base, reserveIncrement: ledgerClose.reserve_inc, transactionCount: ledgerClose.txn_count, diff --git a/src/transaction/order.js b/src/transaction/order.js index 7ab2c863..a266e72b 100644 --- a/src/transaction/order.js +++ b/src/transaction/order.js @@ -1,9 +1,8 @@ /* @flow */ 'use strict'; const utils = require('./utils'); -const validate = utils.common.validate; const offerFlags = utils.common.txFlags.OfferCreate; -const unixToRippleTimestamp = utils.common.unixToRippleTimestamp; +const {validate, iso8601ToRippleTime} = utils.common; import type {Instructions, Prepare} from './types.js'; import type {Order} from '../ledger/transaction-types.js'; @@ -36,7 +35,7 @@ function createOrderTransaction(account: string, order: Order): Object { txJSON.Flags |= offerFlags.FillOrKill; } if (order.expirationTime !== undefined) { - txJSON.Expiration = unixToRippleTimestamp(Date.parse(order.expirationTime)); + txJSON.Expiration = iso8601ToRippleTime(order.expirationTime); } return txJSON; } diff --git a/src/transaction/suspended-payment-creation.js b/src/transaction/suspended-payment-creation.js index bee83e15..eca99f32 100644 --- a/src/transaction/suspended-payment-creation.js +++ b/src/transaction/suspended-payment-creation.js @@ -2,7 +2,7 @@ 'use strict'; const _ = require('lodash'); const utils = require('./utils'); -const {validate, unixToRippleTimestamp, toRippledAmount} = utils.common; +const {validate, iso8601ToRippleTime, toRippledAmount} = utils.common; import type {Instructions, Prepare} from './types.js'; import type {Adjustment, MaxAdjustment, Memo} from '../common/types.js'; @@ -11,8 +11,8 @@ type SuspendedPaymentCreation = { destination: Adjustment, memos?: Array, digest?: string, - allowCancelAfter?: number, - allowExecuteAfter?: number + allowCancelAfter?: string, + allowExecuteAfter?: string } function createSuspendedPaymentCreationTransaction(account: string, @@ -32,10 +32,10 @@ function createSuspendedPaymentCreationTransaction(account: string, txJSON.Digest = payment.digest; } if (payment.allowCancelAfter !== undefined) { - txJSON.CancelAfter = unixToRippleTimestamp(payment.allowCancelAfter); + txJSON.CancelAfter = iso8601ToRippleTime(payment.allowCancelAfter); } if (payment.allowExecuteAfter !== undefined) { - txJSON.FinishAfter = unixToRippleTimestamp(payment.allowExecuteAfter); + txJSON.FinishAfter = iso8601ToRippleTime(payment.allowExecuteAfter); } if (payment.source.tag !== undefined) { txJSON.SourceTag = payment.source.tag; diff --git a/test/fixtures/requests/compute-ledger-hash.json b/test/fixtures/requests/compute-ledger-hash.json index de60dd3e..cf8ff0d1 100644 --- a/test/fixtures/requests/compute-ledger-hash.json +++ b/test/fixtures/requests/compute-ledger-hash.json @@ -1,10 +1,9 @@ { "accepted": true, "stateHash": "D9ABF622DA26EEEE48203085D4BC23B0F77DC6F8724AC33D975DA3CA492D2E44", - "closeTime": 492656470, - "parentCloseTime": 492656460, + "closeTime": "2015-08-12T01:01:10.000Z", + "parentCloseTime": "2015-08-12T01:01:00.000Z", "closeFlags": 0, - "closeTimeHuman": "2015-Aug-12 01:01:10", "closeTimeResolution": 10, "closed": true, "ledgerVersion": 15202439, diff --git a/test/fixtures/requests/prepare-suspended-payment-creation.json b/test/fixtures/requests/prepare-suspended-payment-creation.json index 7e6985ea..2d1ef8a3 100644 --- a/test/fixtures/requests/prepare-suspended-payment-creation.json +++ b/test/fixtures/requests/prepare-suspended-payment-creation.json @@ -15,5 +15,5 @@ "counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM" } }, - "allowCancelAfter": 1440694329002 + "allowCancelAfter": "2014-09-24T21:21:50.000Z" } diff --git a/test/fixtures/responses/get-ledger-full.json b/test/fixtures/responses/get-ledger-full.json index 852ce6e6..56349325 100644 --- a/test/fixtures/responses/get-ledger-full.json +++ b/test/fixtures/responses/get-ledger-full.json @@ -2,12 +2,12 @@ "accepted": true, "closed": true, "stateHash": "2C23D15B6B549123FB351E4B5CDE81C564318EB845449CD43C3EA7953C4DB452", - "closeTime": 410424200, + "closeTime": "2013-01-02T06:43:20.000Z", "closeFlags": 0, "closeTimeResolution": 10, "ledgerHash": "E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E", "ledgerVersion": 38129, - "parentCloseTime": 410424190, + "parentCloseTime": "2013-01-02T06:43:10.000Z", "parentLedgerHash": "3401E5B2E5D3A53EB0891088A5F2D9364BBB6CE5B37A337D2C0660DAF9C4175E", "totalDrops": "99999999999996310", "transactionHash": "DB83BF807416C5B3499A73130F843CF615AB8E797D79FE7D330ADF1BFA93951A", diff --git a/test/fixtures/responses/get-ledger-with-settings-tx.json b/test/fixtures/responses/get-ledger-with-settings-tx.json index 7ec9081b..84b78775 100644 --- a/test/fixtures/responses/get-ledger-with-settings-tx.json +++ b/test/fixtures/responses/get-ledger-with-settings-tx.json @@ -2,13 +2,13 @@ "accepted": true, "closed": true, "stateHash": "2FC964BBFE22DF77A132FE12B5D2B58A09226EBCA73EF2CFF5BE29E56B3315F5", - "closeTime": 441849810, + "closeTime": "2014-01-01T00:03:30.000Z", "closeTimeResolution": 10, "closeFlags": 0, "ledgerHash": "B52AC083396E9119B6CEED69C155B663D58FCA9245917B904BE57FB089E677A4", "ledgerVersion": 4181996, "parentLedgerHash": "599820AB83EF490BA04019E88A90202516D7F39CA169CF639ADCD0A434C7D7DF", - "parentCloseTime": 441849790, + "parentCloseTime": "2014-01-01T00:03:10.000Z", "totalDrops": "99999998243206519", "transactionHash": "49B500E719BB3AC7CB74E3E0D028A01BFE626484F4659CDD98CB4E32BFE0D601", "transactions": [ diff --git a/test/fixtures/responses/get-ledger.json b/test/fixtures/responses/get-ledger.json index 09f97b07..ea9d56f7 100644 --- a/test/fixtures/responses/get-ledger.json +++ b/test/fixtures/responses/get-ledger.json @@ -2,13 +2,13 @@ "accepted": true, "closed": true, "stateHash": "EC028EC32896D537ECCA18D18BEBE6AE99709FEFF9EF72DBD3A7819E918D8B96", - "closeTime": 464908910, + "closeTime": "2014-09-24T21:21:50.000Z", "closeTimeResolution": 10, "closeFlags": 0, "ledgerHash": "0F7ED9F40742D8A513AE86029462B7A6768325583DF8EE21B7EC663019DD6A0F", "ledgerVersion": 9038214, "parentLedgerHash": "4BB9CBE44C39DC67A1BE849C7467FE1A6D1F73949EA163C38A0121A15E04FFDE", - "parentCloseTime": 464908900, + "parentCloseTime": "2014-09-24T21:21:40.000Z", "totalDrops": "99999973964317514", "transactionHash": "ECB730839EB55B1B114D5D1AD2CD9A932C35BA9AB6D3A8C2F08935EAC2BAC239" } diff --git a/test/fixtures/responses/prepare-suspended-payment-creation.json b/test/fixtures/responses/prepare-suspended-payment-creation.json index 202431f7..be8c549b 100644 --- a/test/fixtures/responses/prepare-suspended-payment-creation.json +++ b/test/fixtures/responses/prepare-suspended-payment-creation.json @@ -1,5 +1,5 @@ { - "txJSON": "{\"Flags\":2147483648,\"TransactionType\":\"SuspendedPaymentCreate\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"Amount\":{\"value\":\"0.01\",\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\"},\"CancelAfter\":494009529,\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}", + "txJSON": "{\"Flags\":2147483648,\"TransactionType\":\"SuspendedPaymentCreate\",\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Destination\":\"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo\",\"Amount\":{\"value\":\"0.01\",\"currency\":\"USD\",\"issuer\":\"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM\"},\"CancelAfter\":464908910,\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}", "instructions": { "fee": "0.000012", "sequence": 23,