Skip to content
This repository has been archived by the owner on Sep 2, 2023. It is now read-only.

Commit

Permalink
Merge pull request #362 from lumberj/cherry-pick-notifications
Browse files Browse the repository at this point in the history
Cherry pick Notifications API from develop to release
  • Loading branch information
alandotcom committed Apr 22, 2015
2 parents 6617b39 + c8f60c7 commit f7be058
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 135 deletions.
68 changes: 65 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ We recommend Ripple-REST for users just getting started with Ripple, since it pr

#### Notifications ####

* [Check Notifications - `GET /v1/accounts/{:address}/notifications/{:id}`](#check-notifications)
* [Check Notification - `GET /v1/accounts/{:address}/notifications/{:id}`](#check-notification)
* [Check Notifications - `GET /v1/accounts/{:address}/notifications/`](#check-notifications)

#### Status ####

Expand Down Expand Up @@ -2029,7 +2030,7 @@ Notifications provide a mechanism to monitor for any kind of transactions that m
Notifications are sorted in order of when they occurred, so you can save the most recently-known transaction and easily iterate forward to find any notifications that are newer than that.
## Check Notifications ##
## Check Notification ##
[[Source]<br>](https://github.com/ripple/ripple-rest/blob/develop/api/notifications.js "Source")
Get a notification for the specific transaction hash, along with links to previous and next notifications, if available.
Expand All @@ -2044,7 +2045,7 @@ GET /v1/accounts/{:address}/notifications/{:id}
<!-- </div> -->
[Try it! >](https://ripple.com/build/rest-tool#check-notifications)
[Try it! >](https://ripple.com/build/rest-tool#check-notification)
The following URL parameters are required by this API endpoint:
Expand Down Expand Up @@ -2090,6 +2091,67 @@ The `next_hash` and `next_notification_url` fields work the same way, but they p
*Caution:* If you are accessing the REST API through a proxy, you may not be able to access the URLs as provided. (See [RA-129](https://ripplelabs.atlassian.net/browse/RA-129) for status and details.)
## Check Notifications ##
[[Source]<br>](https://github.com/ripple/ripple-rest/blob/develop/api/notifications.js "Source")
Get the most recent notifications for the specified Ripple account address, along with links to previous and next notifications, if available.
<!-- <div class='multicode'> -->
<!-- *REST* -->
```
GET /v1/accounts/{:address}/notifications/
```
<!-- </div> -->
[Try it! >](https://ripple.com/build/rest-tool#check-notifications)
The following URL parameters are required by this API endpoint:
| Field | Value | Description |
|-------|-------|-------------|
| address | String | The Ripple account address of an account involved in the transaction. |
Optionally, you can also include the following query parameters:
| Field | Type | Description |
|-------|------|-------------|
| exclude_failed | Boolean | If true, only include successful transactions. Defaults to false. |
| earliest_first | Boolean | If true, sort results with the oldest payments first. Defaults to false (sort with the most recent payments first). |
| start\_ledger | Integer (Ledger sequence number) | If provided, exclude payments from ledger versions older than the given ledger. |
| end\_ledger | Integer (Ledger sequence number) | If provided, exclude payments from ledger versions newer than the given ledger. |
| results\_per\_page | Integer | The maximum number of payments to be returned at once. Defaults to 10. |
| page | Integer | The page number for the results to return, if more than `results_per_page` are available. The first page of results is page `1`, the second page is number `2`, and so on. Defaults to `1`. |
#### Response ####
A successful response contains a notification object, for example:
```js
[
{
"success": true,
"notification": {
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
"type": "payment",
"direction": "outgoing",
"state": "validated",
"result": "tesSUCCESS",
"ledger": "8924146",
"hash": "9D591B18EDDD34F0B6CF4223A2940AEA2C3CC778925BABF289E0011CD8FA056E",
"timestamp": "2014-09-17T21:47:00.000Z",
"transaction_url": "http://api.ripple.com:5990/v1/accounts/rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn/payments/9D591B18EDDD34F0B6CF4223A2940AEA2C3CC778925BABF289E0011CD8FA056E",
"previous_hash": "8496C20AEB453803CB80474B59AB1E8FAA26725561EFF5AF41BD588B325AFBA8",
"previous_notification_url": "http://api.ripple.com:5990/v1/accounts/rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn/notifications/8496C20AEB453803CB80474B59AB1E8FAA26725561EFF5AF41BD588B325AFBA8",
"next_hash": "AE79DE34230403EA2769B4DA21A0D4D2FD7A18518DBA0A4C5B6352AFD844D22A",
"next_notification_url": "http://api.ripple.com:5990/v1/accounts/rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn/notifications/AE79DE34230403EA2769B4DA21A0D4D2FD7A18518DBA0A4C5B6352AFD844D22A"
}
]
```
*Caution:* If you are accessing the REST API through a proxy, you may not be able to access the URLs as provided. (See [RA-129](https://ripplelabs.atlassian.net/browse/RA-129) for status and details.)
Expand Down
1 change: 1 addition & 0 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ RippleAPI.prototype = {
getOrder: Orders.getOrder,

getNotification: Notifications.getNotification,
getNotifications: Notifications.getNotifications,

wallet: Wallet,

Expand Down
48 changes: 29 additions & 19 deletions api/lib/notification_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var ripple = require('ripple-lib');
*/
function NotificationParser() {}

NotificationParser.prototype.parse = function(notification_details) {
NotificationParser.prototype.parse = function(notification_details, urlBase) {
var transaction = notification_details.transaction;
var account = notification_details.account;
var previous_transaction_identifier =
Expand All @@ -39,16 +39,17 @@ NotificationParser.prototype.parse = function(notification_details) {
hash: transaction.hash,
timestamp: '',// set below
transaction_url: '', // set below
previous_hash: notification_details.previous_hash,
previous_hash: notification_details.previous_hash || '',
previous_notification_url: '', // set below
next_hash: notification_details.next_hash,
next_hash: notification_details.next_hash || '',
next_notification_url: '', // set below
client_resource_id: notification_details.client_resource_id
};

notification.timestamp = transaction.date ?
new Date(ripple.utils.time.fromRipple(transaction.date)).toISOString() : '';

// Direction
if (account === transaction.Account) {
notification.direction = 'outgoing';
} else if (transaction.TransactionType === 'Payment'
Expand All @@ -57,34 +58,43 @@ NotificationParser.prototype.parse = function(notification_details) {
} else {
notification.direction = 'incoming';
}

// Notification URL

if (notification.type === 'payment') {
notification.transaction_url = '/v1/accounts/' + notification.account
+ '/payments/' + (transaction.from_local_db
notification.transaction_url = urlBase + '/v1/accounts/'
+ notification.account
+ '/payments/'
+ (transaction.from_local_db
? notification.client_resource_id : notification.hash);
} else {
notification.transaction_url = '/v1/transactions/' + notification.hash;
}
if (notification.type === 'offercreate'
} else if (notification.type === 'offercreate'
|| notification.type === 'offercancel') {
notification.type = 'order';
notification.transaction_url = '/v1/accounts/' + notification.account
+ '/orders/' + notification.hash;
notification.transaction_url = urlBase + '/v1/accounts/'
+ notification.account
+ '/orders/' + notification.hash;
} else if (notification.type === 'trustset') {
notification.type = 'trustline';
notification.transaction_url = urlBase + '/v1/transactions/'
+ notification.hash;
} else if (notification.type === 'accountset') {
notification.type = 'settings';
notification.transaction_url = urlBase + '/v1/transactions/'
+ notification.hash;
}

// Next notification URL

if (next_transaction_identifier) {
notification.next_notification_url = '/v1/accounts/' +
notification.account +
'/notifications/' +
next_transaction_identifier;
notification.next_notification_url = urlBase + '/v1/accounts/'
+ notification.account + '/notifications/' + next_transaction_identifier;
}

// Previous notification URL
if (previous_transaction_identifier) {
notification.previous_notification_url = '/v1/accounts/' +
notification.account +
'/notifications/' +
previous_transaction_identifier;
notification.previous_notification_url = urlBase + '/v1/accounts/'
+ notification.account + '/notifications/'
+ previous_transaction_identifier;
}

return notification;
Expand Down
38 changes: 37 additions & 1 deletion api/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
var bignum = require('bignumber.js');
var validator = require('./schema-validator.js');
var ripple = require('ripple-lib');
var _ = require('lodash');
var async = require('async');

function renameCounterpartyToIssuer(amount) {
if (amount && amount.counterparty) {
Expand Down Expand Up @@ -127,6 +129,39 @@ function isValidLedgerWord(ledger) {
return (/^current$|^closed$|^validated$/.test(ledger));
}

function attachDate(api, baseTransactions, callback) {
var groupedTx = _.groupBy(baseTransactions, function(tx) {
return tx.ledger_index;
});

function attachDateToTransactions(_groupedTx, ledger, _callback) {
api.remote.requestLedger({ledger_index: Number(ledger)},
function(err, data) {
if (err) {
return _callback(err);
}

_.each(_groupedTx[ledger], function(tx) {
tx.date = data.ledger.close_time;
});

_callback(null, _groupedTx[ledger]);
}
);
}

// TODO: Decorate _.flatten and make it an async function
async.map(_.keys(groupedTx),
_.partial(attachDateToTransactions, groupedTx),
function(err, results) {
if (err) {
return callback(err);
}
callback(null, _.flatten(results));
});
}


module.exports = {
isValidLedgerSequence: isValidLedgerSequence,
isValidLedgerWord: isValidLedgerWord,
Expand All @@ -138,6 +173,7 @@ module.exports = {
parseCurrencyQuery: parseCurrencyQuery,
txFromRestAmount: txFromRestAmount,
compareTransactions: compareTransactions,
renameCounterpartyToIssuer: renameCounterpartyToIssuer
renameCounterpartyToIssuer: renameCounterpartyToIssuer,
attachDate: attachDate
};

Loading

0 comments on commit f7be058

Please sign in to comment.