diff --git a/README.md b/README.md index 8e068833..8692a194 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,47 @@ -#Ripple JavaScript Library +#The Ripple JavaScript Library -`npm install ripple-lib` +`ripple-lib` connects to the Ripple network via the WebSocket protocol and runs in Node.js as well as in the browser. -This library can connect to the Ripple network via the WebSocket protocol and runs in Node.js as well as in the browser. +###In this file: -* https://ripple.com/wiki/Ripple_JavaScript_library -* https://ripple.com -* https://ripple.com/wiki +1. Overview +2. [Getting `ripple-lib`](README.md#getting-ripple-lib) +3. [Quickstart](README.md#quickstart) -##Getting started +###For additional documentation see: -[ripple-lib.remote](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/remote.js) is responsible for managing connections to rippled servers. +1. [The `ripple-lib` Guides (docs/GUIDES.md)](docs/GUIDES.md) +2. [The `ripple-lib` API Reference (docs/REFERENCE.md)](docs/REFERENCE.md) +3. https://ripple.com/wiki/Ripple_JavaScript_library + +###Also see: + ++ https://ripple.com/wiki ++ https://ripple.com + +##Getting `ripple-lib` + +1. Via npm for Node.js: `npm install ripple-lib` +2. Build from the source using `grunt` and load the minified `ripple-#.#.#-min.js` into your webpage + + +##Quickstart + +`Remote` ([remote.js](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/remote.js)) is the module responsible for managing connections to `rippled` servers: ```js +/* Loading ripple-lib with Node.js */ var Remote = require('ripple-lib').Remote; +/* Loading ripple-lib in a webpage */ +// var Remote = ripple.Remote; + var remote = new Remote({ + // see the API Reference for available options trusted: true, local_signing: true, local_fee: true, + fee_cusion: 1.5, servers: [ { host: 's1.ripple.com' @@ -30,210 +53,9 @@ var remote = new Remote({ remote.connect(function() { /* remote connected */ + + // see the API Reference for available functions }); ``` -##Calling remote commands - -Each remote function returns a `Request` object. This object is an `EventEmitter`. You may listen for success or failure events from each request, or provide a callback. Example: - -```js -var request = remote.request_server_info(); -request.on('success', function(res) { - //handle success -}); -request.on('error', function(err) { - //handle error -}); -request.request(); -``` - -*Or:* - -```js -remote.request_server_info(function(err, res) { - if (err) { - //handle error - } else { - //handle success - } -}); -``` - -##Commands available - -**[request_server_info([callback])](https://ripple.com/wiki/RPC_API#server_info)** - -Returns information about the state of the server. If you are connected to multiple servers and want to select by a particular host, use `request.set_server`. Example: - -```js -var request = remote.request_server_info(); -request.set_server('my.hostname'); -request.callback(function(err, res) { - -}); -request.request(); -``` - -**[request_ledger(ledger, [opts], [callback])](https://ripple.com/wiki/RPC_API#ledger)** - -**request_ledger_header([callback])** - -**[request_ledger_current([callback])](https://ripple.com/wiki/RPC_API#ledger_current)** - -**[request_ledger_entry(type, [callback])](https://ripple.com/wiki/RPC_API#ledger_entry)** - -**[request_subscribe(streams, [callback])](https://ripple.com/wiki/RPC_API#subscribe)** - -Start receiving selected streams from the server. - -**[request_unsubscribe(streams, [callback])](https://ripple.com/wiki/RPC_API#unsubscribe)** - -Stop receiving selected streams from the server. - -**[request_transaction_entry(hash, [ledger_hash], [callback])](https://ripple.com/wiki/RPC_API#transaction_entry)** - -Searches a particular ledger for a transaction hash. Default ledger is the open ledger. - -**[request_tx(hash, [callback])](https://ripple.com/wiki/RPC_API#tx)** - -Searches ledger history for validated transaction hashes. - -**[request_account_info(account, [callback])](https://ripple.com/wiki/RPC_API#account_info)** - -Return information about the specified account. - -``` -{ - ledger_current_index: , - account_data: { - Account: , - Balance: , - Flags: , - LedgerEntryType: , - OwnerCount: , - PreviousTxnID: , - PreviousTxnLgrSeq: , - Sequence: , - index: - } -} -``` - -**[request_account_lines(accountID, account_index, current, [callback])](https://ripple.com/wiki/RPC_API#account_lines)** - -**[request_account_offers(accountID, account_index, current, [callback])](https://ripple.com/wiki/RPC_API#account_offers)** - -Return the specified account's outstanding offers. - -**[request_account_tx(opts, [callback])](https://ripple.com/wiki/RPC_API#account_tx)** - -Fetch a list of transactions that applied to this account. - -Options: - -+ `account` -+ `ledger_index_min` *deprecated, -1* -+ `ledger_index_max` *deprecated, -1* -+ `binary` *false* -+ `count` *false* -+ `descending` *false* -+ `offset` *0* -+ `limit` -+ `forward` *false* -+ `fwd_marker` -+ `rev_marker` - -**[request_book_offers(gets, pays, taker, [callback])](https://ripple.com/wiki/RPC_API#book_offers)** - -Return the offers for an order book as one or more pages. - -**[request_wallet_accounts(seed, [callback])](https://ripple.com/wiki/RPC_API#wallet_accounts)** - -Return a list of accounts for a wallet. - -+ requires trusted remote - -**[request_sign(secret, tx_json, [callback])](https://ripple.com/wiki/RPC_API#sign)** - -Sign a transaction. - -+ requires trusted remote - -**[request_submit([callback])](https://ripple.com/wiki/RPC_API#submit)** - -Submit a transaction to the network. This command is used internally to submit transactions with a greater degree of reliability. See [Submitting a transaction](https://github.com/ripple/ripple-lib#submitting-a-transaction) for details. - -**request_account_balance(account, ledger, [callback])** - -Get the balance for an account. Returns an [Amount](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/amount.js) object. - -**request_account_flags(account, current, [callback])** - -Return the flags for an account. - -**request_owner_count(account, current, [callback])** - -Return the owner count for an account. - -**request_ripple_balance(account, issuer, currency, current, [callback])** - -Return a request to get a ripple balance - -**[request_ripple_path_find(src_account, dst_account, dst_amount, src_currencies, [callback])](https://ripple.com/wiki/RPC_API#path_find)** - -**[request_unl_list([callback])](https://ripple.com/wiki/RPC_API#unl_list)** - -**[request_unl_add(addr, comment, [callback])](https://ripple.com/wiki/RPC_API#unl_add)** - -**[request_unl_delete(node, [callback])](https://ripple.com/wiki/RPC_API#unl_delete)** - -**[request_peers([callback])](https://ripple.com/wiki/RPC_API#peers)** - -**[request_connect(ip, port, [callback])](https://ripple.com/wiki/RPC_API#connect)** - -**transaction([destination], [source], [amount], [callback])** - -Returns a [Transaction](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/transaction.js) object - -##Submitting a transaction - -```js -var Remote = require('ripple-lib').Remote; -var Amount = require('ripple-lib').Amount; - -var MY_ADDRESS = 'rrrMyAddress'; -var MY_SECRET = 'secret'; -var RECIPIENT = 'rrrRecipient'; -var AMOUNT = Amount.from_human('1XRP'); - -var remote = new Remote({ /* configuration */ }); - -remote.connect(function() { - remote.set_secret(MY_ADDRESS, MY_SECRET); - - var transaction = remote.transaction(); - - transaction.payment(MY_ADDRESS, RECIPIENT, AMOUNT); - - transaction.submit(function(err, res) { - /* handle submission errors / success */ - }); -}); -``` - -###Transaction events - -[Transaction](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/transaction.js) objects are EventEmitters. They may emit the following events. - -+ `final` Transaction has erred or succeeded. This event indicates that the transaction has finished processing. -+ `error` Transaction has erred. This event is a final state. -+ `success` Transaction succeeded. This event is a final state. -+ `submitted` Transaction has been submitted to the network. The submission may result in a remote error or success. -+ `proposed` Transaction has been submitted *successfully* to the network. The transaction at this point is awaiting validation in a ledger. -+ `timeout` Transaction submission timed out. The transaction will be resubmitted. -+ `resubmit` Transaction is beginning resubmission. -+ `fee_adjusted` Transaction fee has been adjusted during its pending state. The transaction fee will only be adjusted if the remote is configured for local fees, which it is by default. -+ `abort` Transaction has been aborted. Transactions are only aborted by manual calls to `#abort`. -+ `missing` Four ledgers have closed without detecting validated transaction -+ `lost` Eight ledgers have closed without detecting validated transaction. Consider the transaction lost and err/finalize. +See [The `ripple-lib` Guides](docs/GUIDES.md) and [The `ripple-lib` API Reference](docs/REFERENCE.md) for walkthroughs and details about all of the available functions and options. diff --git a/docs/GUIDES.md b/docs/GUIDES.md new file mode 100644 index 00000000..f9da39d4 --- /dev/null +++ b/docs/GUIDES.md @@ -0,0 +1,194 @@ +#`ripple-lib` Guides + +This file provides step-by-step walkthroughs for some of the most common usages of `ripple-lib`. + +###Guides in this document: + +1. [Connecting to the Ripple network with `Remote`](GUIDES.md#1-connecting-to-the-ripple-network-with-remote) +2. [Using `Remote` functions and `Request` objects](GUIDES.md#2-using-remote-functions-and-request-objects) +3. [Submitting a payment to the network](GUIDES.md#3-submitting-a-payment-to-the-network) + * [A note on transaction fees](GUIDES.md#a-note-on-transaction-fees) +4. [Submitting a trade offer to the network](GUIDES.md#4-submitting-a-trade-offer-to-the-network) +5. [Listening to the network](GUIDES.md#5-listening-to-the-network) + + +###Also see: + +1. [The `ripple-lib` README](../README.md) +2. [The `ripple-lib` API Reference](REFERENCE.md) + +##1. Connecting to the Ripple network with `Remote` + +1. [Get `ripple-lib`](README.md#getting-ripple-lib) +2. Load the `ripple-lib` module into a Node.js file or webpage: + ```js + /* Loading ripple-lib with Node.js */ + var Remote = require('ripple-lib').Remote; + + /* Loading ripple-lib in a webpage */ + // var Remote = ripple.Remote; + ``` +3. Create a new `Remote` and connect to the network: + ```js + var remote = new Remote({options}); + + remote.connect(function() { + /* remote connected, use some remote functions here */ + }); + ``` + __NOTE:__ See the API Reference for available [`Remote` options](REFERENCE.md#1-remote-options) +4. You're connected! Read on to see what to do now. + + +##2. Using `Remote` functions and `Request` objects + +All `Remote` functions return a `Request` object. + +A `Request` is an `EventEmitter` so you can listen for success or failure events -- or, instead, you can provide a callback to the `Remote` function. + +Here is an example, using `request_server_info()`, of how `Remote` functions can be used with event listeners (the first code block) or with a callback (the second block): + ++ Using a `Remote` function with `Request` event listeners: +```js +var request = remote.request_server_info(); +request.on('success', function(res) { + //handle success +}); +request.on('error', function(err) { + //handle error +}); +request.request(); // this triggers the request if it has not already been sent to the server +``` + ++ Using a `Remote` function with a callback: +```js +remote.request_server_info(function(err, res) { + if (err) { + //handle error + } else { + //handle success + } +}); +``` + +__NOTE:__ See the API Reference for available [`Remote` functions](REFERENCE.md#2-remote-functions) + + + + +##3. Submitting a payment to the network + +Submitting a payment transaction to the Ripple network involves connecting to a `Remote`, creating a transaction, signing it with the user's secret, and submitting it to the `rippled` server. Note that the `Amount` module is used to convert human-readable amounts like '1XRP' or '10.50USD' to the type of Amount object used by the Ripple network. + +```js +/* Loading ripple-lib Remote and Amount modules in Node.js */ +var Remote = require('ripple-lib').Remote; +var Amount = require('ripple-lib').Amount; + +/* Loading ripple-lib Remote and Amount modules in a webpage */ +// var Remote = ripple.Remote; +// var Amount = ripple.Amount; + +var MY_ADDRESS = 'rrrMyAddress'; +var MY_SECRET = 'secret'; +var RECIPIENT = 'rrrRecipient'; +var AMOUNT = Amount.from_human('1XRP'); + +var remote = new Remote({ /* Remote options */ }); + +remote.connect(function() { + remote.set_secret(MY_ADDRESS, MY_SECRET); + + var transaction = remote.transaction(); + + transaction.payment(MY_ADDRESS, RECIPIENT, AMOUNT); + + transaction.submit(function(err, res) { + /* handle submission errors / success */ + }); +}); +``` + +###A note on transaction fees + +A full description of network transaction fees can be found on the [Ripple Wiki](https://ripple.com/wiki/Transaction_Fee). + +In short, transaction fees are very small amounts (on the order of ~10) of [XRP drops](https://ripple.com/wiki/Ripple_credits#Notes_on_drops) spent and destroyed with every transaction. They are largely used to account for network load and prevent spam. With `ripple-lib`, transaction fees are calculated locally by default and the fee you are willing to pay is submitted along with your transaction. + +Since the fee required for a transaction may change between the time when the original fee was calculated and the time when the transaction is submitted, it is wise to use the [`fee_cushion`](REFERENCE.md#1-remote-options) to ensure that the transaction will go through. For example, suppose the original fee calculated for a transaction was 10 XRP drops but at the instant the transaction is submitted the server is experiencing a higher load and it has raised its minimum fee to 12 XRP drops. Without a `fee_cusion`, this transaction would not be processed by the server, but with a `fee_cusion` of, say, 1.5 it would be processed and you would just pay the 2 extra XRP drops. + +The [`max_fee`](REFERENCE.md#1-remote-options) option can be used to avoid submitting a transaction to a server that is charging unreasonably high fees. + + +##4. Submitting a trade offer to the network + +Submitting a trade offer to the network is similar to submitting a payment transaction. Here is an example for a trade that expires in 24 hours where you are offering to sell 1 USD in exchange for 100 XRP: + +```js +/* Loading ripple-lib Remote and Amount modules in Node.js */ +var Remote = require('ripple-lib').Remote; +var Amount = require('ripple-lib').Amount; + +/* Loading ripple-lib Remote and Amount modules in a webpage */ +// var Remote = ripple.Remote; +// var Amount = ripple.Amount; + +var MY_ADDRESS = 'rrrMyAddress'; +var MY_SECRET = 'secret'; + +// TAKER_PAYS is the amount that the other party will pay you +// TAKER_GETS is the amount you are offering to them +var TAKER_PAYS = Amount.from_human('100XRP'); +var TAKER_GETS = Amount.from_human('1USD'); + +// EXPIRATION must be a Date object, leave undefined to submit offer that won't expire +var now = new Date(); +var tomorrow = new Date(now.getTime() + (24 * 60 * 60 * 1000)); +var EXPIRATION = tomorrow; + +var remote = new Remote({ /* Remote options */ }); + +remote.connect(function() { + remote.set_secret(MY_ADDRESS, MY_SECRET); + + var transaction = remote.transaction(); + + transaction.offer_create(MY_ADDRESS, TAKER_PAYS, TAKER_GETS, EXPIRATION); + + transaction.submit(function(err, res) { + /* handle submission errors / success */ + }); +}); +``` + +##5. Listening to the network + +In some (relatively rare) cases you may want to subscribe to the network event feed and listen for transactions and the ledger closings. [Ripple.com](http://www.ripple.com) uses this feature of `ripple-lib` to display the live feed on the top of each page and the ledger closing visualization on the [Developers page](http://ripple.com/devs). + +```js + /* Loading ripple-lib with Node.js */ + var Remote = require('ripple-lib').Remote; + + /* Loading ripple-lib in a webpage */ + // var Remote = ripple.Remote; + + var remote = new Remote({options}); + + remote.connect(function() { + remote.on('transaction_all', transactionListener); + remote.on('ledger_closed', ledgerListener); + }); + + function transactionListener (transaction_data) { + // handle transaction_data + // see https://ripple.com/wiki/RPC_API#transactions_stream_messages for the format of transaction_data + } + + function ledgerListener (ledger_data) { + // handle ledger_data + // see https://ripple.com/wiki/RPC_API#ledger_stream_messages for the format of ledger_data + } +``` +* https://ripple.com/wiki/RPC_API#transactions_stream_messages +* https://ripple.com/wiki/RPC_API#ledger_stream_messages + diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md new file mode 100644 index 00000000..e5896cce --- /dev/null +++ b/docs/REFERENCE.md @@ -0,0 +1,244 @@ +#`ripple-lib` API Reference + +__(More examples coming soon!)__ + +###In this document: + +1. [`Remote` options](REFERENCE.md#1-remote-options) +2. [`Remote` functions](REFERENCE.md#2-remote-functions) + + [Server info functions](REFERENCE.md#server-info-functions) + + [Ledger query functions](REFERENCE.md#ledger-query-functions) + + [Transaction query functions](REFERENCE.md#transaction-query-functions) + + [Account query functions](REFERENCE.md#account-query-functions) + + [Order book query functions](REFERENCE.md#order-book-query-functions) + + [Transaction submission functions](REFERENCE.md#transaction-submission-functions) +3. [`Transaction` events](REFERENCE.md#3-transaction-events) +4. [`Amount` objects](REFERENCE.md#4-amount-objects) + + +###Also see: + +1. [The `ripple-lib` README](../README.md) +2. [The `ripple-lib` GUIDES](GUIDES.md) + + +#1. `Remote` options + +```js +/* Loading ripple-lib with Node.js */ +var Remote = require('ripple-lib').Remote; + +/* Loading ripple-lib in a webpage */ +// var Remote = ripple.Remote; + +var remote = new Remote({options}); +``` + +A new `Remote` can be created with the following options: + ++ `trace` Log all of the events emitted (boolean) ++ `max_listeners` Set maxListeners for remote; prevents EventEmitter warnings (number) ++ `connection_offset` Connect to remote servers on supplied interval (number in seconds) ++ `trusted` truthy, if remote is trusted (boolean) ++ `local_fee` Set whether the transaction fee range will be set locally (boolean, default is true, see [A note on transaction fees](GUIDES.md#a-note-on-transaction-fees)) ++ `fee_cushion` Extra fee multiplier to account for async fee changes (number, e.g. 1.5, see [A note on transaction fees](GUIDES.md#a-note-on-transaction-fees)) ++ `max_fee` Maximum acceptable transaction fee (number in [XRP drops](https://ripple.com/wiki/Ripple_credits#Notes_on_drops), see [A note on transaction fees](GUIDES.md#a-note-on-transaction-fees)) ++ `servers` Array of server objects of the following form: + +```js +{ + host: + , port: + , secure: +} +``` + + +#2. `Remote` functions + + + +##Server info functions + +**[request_server_info([callback])](https://ripple.com/wiki/RPC_API#server_info)** + +Returns information about the state of the server. If you are connected to multiple servers and want to select by a particular host, use `request.set_server`. Example: + +```js +var request = remote.request_server_info(); +request.set_server('my.hostname'); +request.callback(function(err, res) { + +}); +request.request(); +``` + +**[request_unl_list([callback])](https://ripple.com/wiki/RPC_API#unl_list)** + +**[request_unl_add(addr, comment, [callback])](https://ripple.com/wiki/RPC_API#unl_add)** + +**[request_unl_delete(node, [callback])](https://ripple.com/wiki/RPC_API#unl_delete)** + +**[request_peers([callback])](https://ripple.com/wiki/RPC_API#peers)** + + +**[request_connect(ip, port, [callback])](https://ripple.com/wiki/RPC_API#connect)** + + + +##Ledger query functions + +**[request_ledger(ledger, [opts], [callback])](https://ripple.com/wiki/RPC_API#ledger)** + +**request_ledger_header([callback])** + +**[request_ledger_current([callback])](https://ripple.com/wiki/RPC_API#ledger_current)** + +**[request_ledger_entry(type, [callback])](https://ripple.com/wiki/RPC_API#ledger_entry)** + +**[request_subscribe(streams, [callback])](https://ripple.com/wiki/RPC_API#subscribe)** + +Start receiving selected streams from the server. + +**[request_unsubscribe(streams, [callback])](https://ripple.com/wiki/RPC_API#unsubscribe)** + +Stop receiving selected streams from the server. + + + + +##Transaction query functions + +**[request_transaction_entry(hash, [ledger_hash], [callback])](https://ripple.com/wiki/RPC_API#transaction_entry)** + +Searches a particular ledger for a transaction hash. Default ledger is the open ledger. + +**[request_tx(hash, [callback])](https://ripple.com/wiki/RPC_API#tx)** + +Searches ledger history for validated transaction hashes. + + + + +##Account query functions + +**[request_account_info(account, [callback])](https://ripple.com/wiki/RPC_API#account_info)** + +Return information about the specified account. + +``` +{ + ledger_current_index: , + account_data: { + Account: , + Balance: , + Flags: , + LedgerEntryType: , + OwnerCount: , + PreviousTxnID: , + PreviousTxnLgrSeq: , + Sequence: , + index: + } +} +``` + +**[request_account_lines(accountID, account_index, current, [callback])](https://ripple.com/wiki/RPC_API#account_lines)** + +**[request_account_offers(accountID, account_index, current, [callback])](https://ripple.com/wiki/RPC_API#account_offers)** + +Return the specified account's outstanding offers. + +**[request_account_tx(opts, [callback])](https://ripple.com/wiki/RPC_API#account_tx)** + +Fetch a list of transactions that applied to this account. + +Options: + ++ `account` ++ `ledger_index_min` *deprecated, -1* ++ `ledger_index_max` *deprecated, -1* ++ `binary` *false* ++ `count` *false* ++ `descending` *false* ++ `offset` *0* ++ `limit` ++ `forward` *false* ++ `fwd_marker` ++ `rev_marker` + +**[request_wallet_accounts(seed, [callback])](https://ripple.com/wiki/RPC_API#wallet_accounts)** + +Return a list of accounts for a wallet. + ++ requires trusted remote + +**request_account_balance(account, ledger, [callback])** + +Get the balance for an account. Returns an [Amount](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/amount.js) object. + +**request_account_flags(account, current, [callback])** + +Return the flags for an account. + +**request_owner_count(account, current, [callback])** + +Return the owner count for an account. + +**request_ripple_balance(account, issuer, currency, current, [callback])** + +Return a request to get a ripple balance + + + + +##Order book query functions + +**[request_book_offers(gets, pays, taker, [callback])](https://ripple.com/wiki/RPC_API#book_offers)** + +Return the offers for an order book as one or more pages. + + + + +##Transaction submission functions + +**[request_sign(secret, tx_json, [callback])](https://ripple.com/wiki/RPC_API#sign)** + +Sign a transaction. + ++ requires trusted remote + +**[request_submit([callback])](https://ripple.com/wiki/RPC_API#submit)** + +Submit a transaction to the network. This command is used internally to submit transactions with a greater degree of reliability. See [Submitting a payment to the network](GUIDES.md#3-submitting-a-payment-to-the-network) for details. + + +**[request_ripple_path_find(src_account, dst_account, dst_amount, src_currencies, [callback])](https://ripple.com/wiki/RPC_API#path_find)** + + +**transaction([destination], [source], [amount], [callback])** + +Returns a [Transaction](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/transaction.js) object + + +#3. Transaction events + +[Transaction](https://github.com/ripple/ripple-lib/blob/develop/src/js/ripple/transaction.js) objects are EventEmitters. They may emit the following events. + ++ `final` Transaction has erred or succeeded. This event indicates that the transaction has finished processing. ++ `error` Transaction has erred. This event is a final state. ++ `success` Transaction succeeded. This event is a final state. ++ `submitted` Transaction has been submitted to the network. The submission may result in a remote error or success. ++ `proposed` Transaction has been submitted *successfully* to the network. The transaction at this point is awaiting validation in a ledger. ++ `timeout` Transaction submission timed out. The transaction will be resubmitted. ++ `resubmit` Transaction is beginning resubmission. ++ `fee_adjusted` Transaction fee has been adjusted during its pending state. The transaction fee will only be adjusted if the remote is configured for local fees, which it is by default. ++ `abort` Transaction has been aborted. Transactions are only aborted by manual calls to `#abort`. ++ `missing` Four ledgers have closed without detecting validated transaction ++ `lost` Eight ledgers have closed without detecting validated transaction. Consider the transaction lost and err/finalize. + + +#4. Amount objects + +Coming Soon