From a574e1158a842f7822fcf9410b28ab6cc009829a Mon Sep 17 00:00:00 2001 From: Ben Sharafian Date: Fri, 17 Feb 2017 15:45:32 +0100 Subject: [PATCH] Add transactions for payment channels --- src/api.js | 9 ++ src/common/schema-validator.js | 8 ++ .../input/prepare-payment-channel-claim.json | 18 +++ .../input/prepare-payment-channel-create.json | 18 +++ .../input/prepare-payment-channel-fund.json | 18 +++ src/common/schemas/objects/public-key.json | 7 ++ src/common/schemas/objects/signature.json | 7 ++ src/common/schemas/objects/tx-type.json | 3 +- .../schemas/output/get-transaction.json | 18 +++ .../specifications/payment-channel-claim.json | 38 ++++++ .../payment-channel-create.json | 39 ++++++ .../specifications/payment-channel-fund.json | 23 ++++ src/common/txflags.js | 5 + src/common/validate.js | 6 + src/ledger/parse/payment-channel-claim.js | 22 ++++ src/ledger/parse/payment-channel-create.js | 21 ++++ src/ledger/parse/payment-channel-fund.js | 17 +++ src/ledger/parse/transaction.js | 9 ++ src/transaction/payment-channel-claim.js | 74 ++++++++++++ src/transaction/payment-channel-create.js | 53 ++++++++ src/transaction/payment-channel-fund.js | 41 +++++++ test/api-test.js | 114 ++++++++++++++++++ test/fixtures/requests/index.js | 15 +++ .../prepare-payment-channel-claim-close.json | 8 ++ .../prepare-payment-channel-claim-full.json | 9 ++ ...re-payment-channel-claim-no-signature.json | 6 + .../prepare-payment-channel-claim-renew.json | 8 ++ .../prepare-payment-channel-claim.json | 3 + .../prepare-payment-channel-create-full.json | 9 ++ .../prepare-payment-channel-create.json | 6 + .../prepare-payment-channel-fund-full.json | 5 + .../prepare-payment-channel-fund.json | 4 + ...get-transaction-payment-channel-claim.json | 28 +++++ ...et-transaction-payment-channel-create.json | 29 +++++ .../get-transaction-payment-channel-fund.json | 26 ++++ test/fixtures/responses/index.js | 19 +++ .../prepare-payment-channel-claim-close.json | 8 ++ .../prepare-payment-channel-claim-renew.json | 8 ++ .../prepare-payment-channel-claim.json | 8 ++ .../prepare-payment-channel-create-full.json | 8 ++ .../prepare-payment-channel-create.json | 8 ++ .../prepare-payment-channel-fund-full.json | 8 ++ .../prepare-payment-channel-fund.json | 8 ++ test/fixtures/rippled/index.js | 3 + .../rippled/tx/payment-channel-claim.json | 70 +++++++++++ .../rippled/tx/payment-channel-create.json | 86 +++++++++++++ .../rippled/tx/payment-channel-fund.json | 69 +++++++++++ test/mock-rippled.js | 9 ++ 48 files changed, 1035 insertions(+), 1 deletion(-) create mode 100644 src/common/schemas/input/prepare-payment-channel-claim.json create mode 100644 src/common/schemas/input/prepare-payment-channel-create.json create mode 100644 src/common/schemas/input/prepare-payment-channel-fund.json create mode 100644 src/common/schemas/objects/public-key.json create mode 100644 src/common/schemas/objects/signature.json create mode 100644 src/common/schemas/specifications/payment-channel-claim.json create mode 100644 src/common/schemas/specifications/payment-channel-create.json create mode 100644 src/common/schemas/specifications/payment-channel-fund.json create mode 100644 src/ledger/parse/payment-channel-claim.js create mode 100644 src/ledger/parse/payment-channel-create.js create mode 100644 src/ledger/parse/payment-channel-fund.js create mode 100644 src/transaction/payment-channel-claim.js create mode 100644 src/transaction/payment-channel-create.js create mode 100644 src/transaction/payment-channel-fund.js create mode 100644 test/fixtures/requests/prepare-payment-channel-claim-close.json create mode 100644 test/fixtures/requests/prepare-payment-channel-claim-full.json create mode 100644 test/fixtures/requests/prepare-payment-channel-claim-no-signature.json create mode 100644 test/fixtures/requests/prepare-payment-channel-claim-renew.json create mode 100644 test/fixtures/requests/prepare-payment-channel-claim.json create mode 100644 test/fixtures/requests/prepare-payment-channel-create-full.json create mode 100644 test/fixtures/requests/prepare-payment-channel-create.json create mode 100644 test/fixtures/requests/prepare-payment-channel-fund-full.json create mode 100644 test/fixtures/requests/prepare-payment-channel-fund.json create mode 100644 test/fixtures/responses/get-transaction-payment-channel-claim.json create mode 100644 test/fixtures/responses/get-transaction-payment-channel-create.json create mode 100644 test/fixtures/responses/get-transaction-payment-channel-fund.json create mode 100644 test/fixtures/responses/prepare-payment-channel-claim-close.json create mode 100644 test/fixtures/responses/prepare-payment-channel-claim-renew.json create mode 100644 test/fixtures/responses/prepare-payment-channel-claim.json create mode 100644 test/fixtures/responses/prepare-payment-channel-create-full.json create mode 100644 test/fixtures/responses/prepare-payment-channel-create.json create mode 100644 test/fixtures/responses/prepare-payment-channel-fund-full.json create mode 100644 test/fixtures/responses/prepare-payment-channel-fund.json create mode 100644 test/fixtures/rippled/tx/payment-channel-claim.json create mode 100644 test/fixtures/rippled/tx/payment-channel-create.json create mode 100644 test/fixtures/rippled/tx/payment-channel-fund.json diff --git a/src/api.js b/src/api.js index c8cdf24b..0f872be3 100644 --- a/src/api.js +++ b/src/api.js @@ -42,6 +42,12 @@ const prepareEscrowExecution = require('./transaction/escrow-execution') const prepareEscrowCancellation = require('./transaction/escrow-cancellation') +const preparePaymentChannelCreate = + require('./transaction/payment-channel-create') +const preparePaymentChannelFund = + require('./transaction/payment-channel-fund') +const preparePaymentChannelClaim = + require('./transaction/payment-channel-claim') const prepareSettings = require('./transaction/settings') const sign = require('./transaction/sign') const combine = require('./transaction/combine') @@ -130,6 +136,9 @@ _.assign(RippleAPI.prototype, { prepareEscrowCreation, prepareEscrowExecution, prepareEscrowCancellation, + preparePaymentChannelCreate, + preparePaymentChannelFund, + preparePaymentChannelClaim, prepareSettings, sign, combine, diff --git a/src/common/schema-validator.js b/src/common/schema-validator.js index 97628e9f..bd357457 100644 --- a/src/common/schema-validator.js +++ b/src/common/schema-validator.js @@ -16,11 +16,13 @@ function loadSchemas() { require('./schemas/objects/hash128.json'), require('./schemas/objects/hash256.json'), require('./schemas/objects/sequence.json'), + require('./schemas/objects/signature.json'), require('./schemas/objects/issue.json'), require('./schemas/objects/ledgerversion.json'), require('./schemas/objects/max-adjustment.json'), require('./schemas/objects/memo.json'), require('./schemas/objects/memos.json'), + require('./schemas/objects/public-key.json'), require('./schemas/objects/uint32.json'), require('./schemas/objects/value.json'), require('./schemas/objects/source-adjustment.json'), @@ -51,6 +53,9 @@ function loadSchemas() { require('./schemas/specifications/order.json'), require('./schemas/specifications/escrow-execution.json'), require('./schemas/specifications/escrow-creation.json'), + require('./schemas/specifications/payment-channel-create.json'), + require('./schemas/specifications/payment-channel-fund.json'), + require('./schemas/specifications/payment-channel-claim.json'), require('./schemas/specifications/trustline.json'), require('./schemas/output/sign.json'), require('./schemas/output/submit.json'), @@ -91,6 +96,9 @@ function loadSchemas() { require('./schemas/input/prepare-escrow-creation.json'), require('./schemas/input/prepare-escrow-cancellation.json'), require('./schemas/input/prepare-escrow-execution.json'), + require('./schemas/input/prepare-payment-channel-create.json'), + require('./schemas/input/prepare-payment-channel-fund.json'), + require('./schemas/input/prepare-payment-channel-claim.json'), require('./schemas/input/compute-ledger-hash.json'), require('./schemas/input/sign.json'), require('./schemas/input/submit.json'), diff --git a/src/common/schemas/input/prepare-payment-channel-claim.json b/src/common/schemas/input/prepare-payment-channel-claim.json new file mode 100644 index 00000000..b7ec49dd --- /dev/null +++ b/src/common/schemas/input/prepare-payment-channel-claim.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "preparePaymentChannelClaimParameters", + "type": "object", + "properties": { + "address": { + "$ref": "address", + "description": "The address of the account that is creating the transaction." + }, + "paymentChannelClaim": { + "$ref": "paymentChannelClaim", + "description": "Details of the channel and claim." + }, + "instructions": {"$ref": "instructions"} + }, + "additionalProperties": false, + "required": ["address", "paymentChannelClaim"] +} diff --git a/src/common/schemas/input/prepare-payment-channel-create.json b/src/common/schemas/input/prepare-payment-channel-create.json new file mode 100644 index 00000000..158eb702 --- /dev/null +++ b/src/common/schemas/input/prepare-payment-channel-create.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "preparePaymentChannelCreateParameters", + "type": "object", + "properties": { + "address": { + "$ref": "address", + "description": "The address of the account that is creating the transaction." + }, + "paymentChannelCreate": { + "$ref": "paymentChannelCreate", + "description": "The specification of the payment channel to create." + }, + "instructions": {"$ref": "instructions"} + }, + "additionalProperties": false, + "required": ["address", "paymentChannelCreate"] +} diff --git a/src/common/schemas/input/prepare-payment-channel-fund.json b/src/common/schemas/input/prepare-payment-channel-fund.json new file mode 100644 index 00000000..940e45c4 --- /dev/null +++ b/src/common/schemas/input/prepare-payment-channel-fund.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "preparePaymentChannelFundParameters", + "type": "object", + "properties": { + "address": { + "$ref": "address", + "description": "The address of the account that is creating the transaction." + }, + "paymentChannelFund": { + "$ref": "paymentChannelFund", + "description": "The channel to fund, and the details of how to fund it." + }, + "instructions": {"$ref": "instructions"} + }, + "additionalProperties": false, + "required": ["address", "paymentChannelFund"] +} diff --git a/src/common/schemas/objects/public-key.json b/src/common/schemas/objects/public-key.json new file mode 100644 index 00000000..3b236487 --- /dev/null +++ b/src/common/schemas/objects/public-key.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "publicKey", + "description": "The hexadecimal representation of a secp256k1 or Ed25519 public key.", + "type": "string", + "pattern": "^[A-F0-9]+$" +} diff --git a/src/common/schemas/objects/signature.json b/src/common/schemas/objects/signature.json new file mode 100644 index 00000000..ac108b21 --- /dev/null +++ b/src/common/schemas/objects/signature.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "signature", + "description": "The hexadecimal representation of a signature.", + "type": "string", + "pattern": "^[A-F0-9]+$" +} diff --git a/src/common/schemas/objects/tx-type.json b/src/common/schemas/objects/tx-type.json index f6298560..226fa4df 100644 --- a/src/common/schemas/objects/tx-type.json +++ b/src/common/schemas/objects/tx-type.json @@ -6,5 +6,6 @@ "type": "string", "enum": ["payment", "order", "orderCancellation", "trustline", "settings", "escrowCreation", "escrowCancellation", - "escrowExecution"] + "escrowExecution", "paymentChannelCreate", + "paymentChannelFund", "paymentChannelClaim"] } diff --git a/src/common/schemas/output/get-transaction.json b/src/common/schemas/output/get-transaction.json index d5918eb9..9914d5a1 100644 --- a/src/common/schemas/output/get-transaction.json +++ b/src/common/schemas/output/get-transaction.json @@ -74,6 +74,24 @@ "type": {"enum": ["escrowExecution"]}, "specification": {"$ref": "escrowExecution"} } + }, + { + "properties": { + "type": {"enum": ["paymentChannelCreate"]}, + "specification": {"$ref": "paymentChannelCreate"} + } + }, + { + "properties": { + "type": {"enum": ["paymentChannelFund"]}, + "specification": {"$ref": "paymentChannelFund"} + } + }, + { + "properties": { + "type": {"enum": ["paymentChannelClaim"]}, + "specification": {"$ref": "paymentChannelClaim"} + } } ] } diff --git a/src/common/schemas/specifications/payment-channel-claim.json b/src/common/schemas/specifications/payment-channel-claim.json new file mode 100644 index 00000000..f1762561 --- /dev/null +++ b/src/common/schemas/specifications/payment-channel-claim.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "paymentChannelClaim", + "link": "payment-channel-claim", + "type": "object", + "properties": { + "channel": { + "$ref": "hash256", + "description": "256-bit hexadecimal channel identifier." + }, + "amount": { + "$ref": "value", + "description": "XRP balance of this channel after claim is processed." + }, + "balance": { + "$ref": "value", + "description": "Amount of XRP authorized by signature." + }, + "signature": { + "$ref": "signature", + "description": "Signature of this claim." + }, + "publicKey": { + "$ref": "publicKey", + "description": "Public key of the channel's sender" + }, + "renew": { + "type": "boolean", + "description": "Clear the channel's expiration time." + }, + "close": { + "type": "boolean", + "description": "Request to close the channel." + } + }, + "required": ["channel"], + "additionalProperties": false +} diff --git a/src/common/schemas/specifications/payment-channel-create.json b/src/common/schemas/specifications/payment-channel-create.json new file mode 100644 index 00000000..d08bd50e --- /dev/null +++ b/src/common/schemas/specifications/payment-channel-create.json @@ -0,0 +1,39 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "paymentChannelCreate", + "link": "payment-channel-create", + "type": "object", + "properties": { + "amount": { + "$ref": "value", + "description": "Amount of XRP for sender to set aside in this channel." + }, + "destination": { + "$ref": "address", + "description": "Address to receive XRP claims against this channel." + }, + "settleDelay": { + "type": "number", + "description": "Amount of time the source address must wait before closing the channel if it has unclaimed XRP." + }, + "publicKey": { + "$ref": "publicKey", + "description": "Public key of the key pair the source will use to sign claims against this channel." + }, + "cancelAfter": { + "type": "string", + "format": "date-time", + "description": "Time when this channel expires." + }, + "sourceTag": { + "$ref": "tag", + "description": "Source tag." + }, + "destinationTag": { + "$ref": "tag", + "description": "Destination tag." + } + }, + "required": ["amount", "destination", "settleDelay", "publicKey"], + "additionalProperties": false +} diff --git a/src/common/schemas/specifications/payment-channel-fund.json b/src/common/schemas/specifications/payment-channel-fund.json new file mode 100644 index 00000000..9bc0dd7e --- /dev/null +++ b/src/common/schemas/specifications/payment-channel-fund.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "paymentChannelFund", + "link": "payment-channel-fund", + "type": "object", + "properties": { + "amount": { + "$ref": "value", + "description": "Amount of XRP to fund the channel with." + }, + "channel": { + "$ref": "hash256", + "description": "256-bit hexadecimal channel identifier." + }, + "expiration": { + "type": "string", + "format": "date-time", + "description": "New expiration for this channel." + } + }, + "required": ["amount", "channel"], + "additionalProperties": false +} diff --git a/src/common/txflags.js b/src/common/txflags.js index 6ad7b888..094e0a43 100644 --- a/src/common/txflags.js +++ b/src/common/txflags.js @@ -35,6 +35,11 @@ const txFlags = { NoRippleDirect: 0x00010000, PartialPayment: 0x00020000, LimitQuality: 0x00040000 + }, + + PaymentChannelClaim: { + Renew: 0x00010000, + Close: 0x00020000 } } diff --git a/src/common/validate.js b/src/common/validate.js index 901619ff..7d91490e 100644 --- a/src/common/validate.js +++ b/src/common/validate.js @@ -46,6 +46,12 @@ module.exports = { 'prepareEscrowCancellationParameters'), prepareEscrowExecution: _.partial(schemaValidate, 'prepareEscrowExecutionParameters'), + preparePaymentChannelCreate: _.partial(schemaValidate, + 'preparePaymentChannelCreateParameters'), + preparePaymentChannelFund: _.partial(schemaValidate, + 'preparePaymentChannelFundParameters'), + preparePaymentChannelClaim: _.partial(schemaValidate, + 'preparePaymentChannelClaimParameters'), sign: _.partial(schemaValidate, 'signParameters'), combine: _.partial(schemaValidate, 'combineParameters'), submit: _.partial(schemaValidate, 'submitParameters'), diff --git a/src/ledger/parse/payment-channel-claim.js b/src/ledger/parse/payment-channel-claim.js new file mode 100644 index 00000000..ee8420e3 --- /dev/null +++ b/src/ledger/parse/payment-channel-claim.js @@ -0,0 +1,22 @@ +/* @flow */ +'use strict' // eslint-disable-line strict +const assert = require('assert') +const utils = require('./utils') +const parseAmount = require('./amount') +const claimFlags = utils.txFlags.PaymentChannelClaim + +function parsePaymentChannelClaim(tx: Object): Object { + assert(tx.TransactionType === 'PaymentChannelClaim') + + return utils.removeUndefined({ + channel: tx.Channel, + balance: tx.Balance && parseAmount(tx.Balance).value, + amount: tx.Amount && parseAmount(tx.Amount).value, + signature: tx.Signature, + publicKey: tx.PublicKey, + renew: Boolean(tx.Flags & claimFlags.Renew) || undefined, + close: Boolean(tx.Flags & claimFlags.Close) || undefined + }) +} + +module.exports = parsePaymentChannelClaim diff --git a/src/ledger/parse/payment-channel-create.js b/src/ledger/parse/payment-channel-create.js new file mode 100644 index 00000000..32fd205b --- /dev/null +++ b/src/ledger/parse/payment-channel-create.js @@ -0,0 +1,21 @@ +/* @flow */ +'use strict' // eslint-disable-line strict +const assert = require('assert') +const utils = require('./utils') +const parseAmount = require('./amount') + +function parsePaymentChannelCreate(tx: Object): Object { + assert(tx.TransactionType === 'PaymentChannelCreate') + + return utils.removeUndefined({ + amount: parseAmount(tx.Amount).value, + destination: tx.Destination, + settleDelay: tx.SettleDelay, + publicKey: tx.PublicKey, + cancelAfter: tx.CancelAfter && utils.parseTimestamp(tx.CancelAfter), + sourceTag: tx.SourceTag, + destinationTag: tx.DestinationTag + }) +} + +module.exports = parsePaymentChannelCreate diff --git a/src/ledger/parse/payment-channel-fund.js b/src/ledger/parse/payment-channel-fund.js new file mode 100644 index 00000000..ce6369b2 --- /dev/null +++ b/src/ledger/parse/payment-channel-fund.js @@ -0,0 +1,17 @@ +/* @flow */ +'use strict' // eslint-disable-line strict +const assert = require('assert') +const utils = require('./utils') +const parseAmount = require('./amount') + +function parsePaymentChannelFund(tx: Object): Object { + assert(tx.TransactionType === 'PaymentChannelFund') + + return utils.removeUndefined({ + channel: tx.Channel, + amount: parseAmount(tx.Amount).value, + expiration: tx.Expiration && utils.parseTimestamp(tx.Expiration) + }) +} + +module.exports = parsePaymentChannelFund diff --git a/src/ledger/parse/transaction.js b/src/ledger/parse/transaction.js index 6ff656b2..8659fade 100644 --- a/src/ledger/parse/transaction.js +++ b/src/ledger/parse/transaction.js @@ -10,6 +10,9 @@ const parseSettings = require('./settings') const parseEscrowCreation = require('./escrow-creation') const parseEscrowExecution = require('./escrow-execution') const parseEscrowCancellation = require('./escrow-cancellation') +const parsePaymentChannelCreate = require('./payment-channel-create') +const parsePaymentChannelFund = require('./payment-channel-fund') +const parsePaymentChannelClaim = require('./payment-channel-claim') const parseFeeUpdate = require('./fee-update') const parseAmendment = require('./amendment') @@ -24,6 +27,9 @@ function parseTransactionType(type) { EscrowCreate: 'escrowCreation', EscrowFinish: 'escrowExecution', EscrowCancel: 'escrowCancellation', + PaymentChannelCreate: 'paymentChannelCreate', + PaymentChannelFund: 'paymentChannelFund', + PaymentChannelClaim: 'paymentChannelClaim', SignerListSet: 'settings', SetFee: 'feeUpdate', // pseudo-transaction EnableAmendment: 'amendment' // pseudo-transaction @@ -42,6 +48,9 @@ function parseTransaction(tx: Object): Object { 'escrowCreation': parseEscrowCreation, 'escrowExecution': parseEscrowExecution, 'escrowCancellation': parseEscrowCancellation, + 'paymentChannelCreate': parsePaymentChannelCreate, + 'paymentChannelFund': parsePaymentChannelFund, + 'paymentChannelClaim': parsePaymentChannelClaim, 'feeUpdate': parseFeeUpdate, 'amendment': parseAmendment } diff --git a/src/transaction/payment-channel-claim.js b/src/transaction/payment-channel-claim.js new file mode 100644 index 00000000..e5ee13af --- /dev/null +++ b/src/transaction/payment-channel-claim.js @@ -0,0 +1,74 @@ +/* @flow */ +'use strict' // eslint-disable-line strict +const utils = require('./utils') +const ValidationError = utils.common.errors.ValidationError +const claimFlags = utils.common.txFlags.PaymentChannelClaim +const {validate, xrpToDrops} = utils.common +import type {Instructions, Prepare} from './types.js' + +type PaymentChannelClaim = { + channel: string, + balance?: string, + amount?: string, + signature?: string, + publicKey?: string, + renew?: boolean, + close?: boolean +} + +function createPaymentChannelClaimTransaction(account: string, + claim: PaymentChannelClaim +): Object { + const txJSON = { + Account: account, + TransactionType: 'PaymentChannelClaim', + Channel: claim.channel, + Flags: 0 + } + + if (claim.balance !== undefined) { + txJSON.Balance = xrpToDrops(claim.balance) + } + if (claim.amount !== undefined) { + txJSON.Amount = xrpToDrops(claim.amount) + } + + if (Boolean(claim.signature) !== Boolean(claim.publicKey)) { + throw new ValidationError('"signature" and "publicKey" fields on' + + ' PaymentChannelClaim must only be specified together.') + } + + if (claim.signature !== undefined) { + txJSON.Signature = claim.signature + } + if (claim.publicKey !== undefined) { + txJSON.PublicKey = claim.publicKey + } + + if (claim.renew === true && claim.close === true) { + throw new ValidationError('"renew" and "close" flags on PaymentChannelClaim' + + ' are mutually exclusive') + } + + if (claim.renew === true) { + txJSON.Flags |= claimFlags.Renew + } + if (claim.close === true) { + txJSON.Flags |= claimFlags.Close + } + + return txJSON +} + +function preparePaymentChannelClaim(address: string, + paymentChannelClaim: PaymentChannelClaim, + instructions: Instructions = {} +): Promise { + validate.preparePaymentChannelClaim( + {address, paymentChannelClaim, instructions}) + const txJSON = createPaymentChannelClaimTransaction( + address, paymentChannelClaim) + return utils.prepareTransaction(txJSON, this, instructions) +} + +module.exports = preparePaymentChannelClaim diff --git a/src/transaction/payment-channel-create.js b/src/transaction/payment-channel-create.js new file mode 100644 index 00000000..4cdbfa71 --- /dev/null +++ b/src/transaction/payment-channel-create.js @@ -0,0 +1,53 @@ +/* @flow */ +'use strict' // eslint-disable-line strict +const utils = require('./utils') +const {validate, iso8601ToRippleTime, xrpToDrops} = utils.common +import type {Instructions, Prepare} from './types.js' + +type PaymentChannelCreate = { + amount: string, + destination: string, + settleDelay: number, + publicKey: string, + cancelAfter?: string, + sourceTag?: number, + destinationTag?: number +} + +function createPaymentChannelCreateTransaction(account: string, + paymentChannel: PaymentChannelCreate +): Object { + const txJSON: Object = { + Account: account, + TransactionType: 'PaymentChannelCreate', + Amount: xrpToDrops(paymentChannel.amount), + Destination: paymentChannel.destination, + SettleDelay: paymentChannel.settleDelay, + PublicKey: paymentChannel.publicKey.toUpperCase() + } + + if (paymentChannel.cancelAfter !== undefined) { + txJSON.CancelAfter = iso8601ToRippleTime(paymentChannel.cancelAfter) + } + if (paymentChannel.sourceTag !== undefined) { + txJSON.SourceTag = paymentChannel.sourceTag + } + if (paymentChannel.destinationTag !== undefined) { + txJSON.DestinationTag = paymentChannel.destinationTag + } + + return txJSON +} + +function preparePaymentChannelCreate(address: string, + paymentChannelCreate: PaymentChannelCreate, + instructions: Instructions = {} +): Promise { + validate.preparePaymentChannelCreate( + {address, paymentChannelCreate, instructions}) + const txJSON = createPaymentChannelCreateTransaction( + address, paymentChannelCreate) + return utils.prepareTransaction(txJSON, this, instructions) +} + +module.exports = preparePaymentChannelCreate diff --git a/src/transaction/payment-channel-fund.js b/src/transaction/payment-channel-fund.js new file mode 100644 index 00000000..fa90997e --- /dev/null +++ b/src/transaction/payment-channel-fund.js @@ -0,0 +1,41 @@ +/* @flow */ +'use strict' // eslint-disable-line strict +const utils = require('./utils') +const {validate, iso8601ToRippleTime, xrpToDrops} = utils.common +import type {Instructions, Prepare} from './types.js' + +type PaymentChannelFund = { + channel: string, + amount: string, + expiration?: string +} + +function createPaymentChannelFundTransaction(account: string, + fund: PaymentChannelFund +): Object { + const txJSON = { + Account: account, + TransactionType: 'PaymentChannelFund', + Channel: fund.channel, + Amount: xrpToDrops(fund.amount) + } + + if (fund.expiration !== undefined) { + txJSON.Expiration = iso8601ToRippleTime(fund.expiration) + } + + return txJSON +} + +function preparePaymentChannelFund(address: string, + paymentChannelFund: PaymentChannelFund, + instructions: Instructions = {} +): Promise { + validate.preparePaymentChannelFund( + {address, paymentChannelFund, instructions}) + const txJSON = createPaymentChannelFundTransaction( + address, paymentChannelFund) + return utils.prepareTransaction(txJSON, this, instructions) +} + +module.exports = preparePaymentChannelFund diff --git a/test/api-test.js b/test/api-test.js index 9b8df950..17be3698 100644 --- a/test/api-test.js +++ b/test/api-test.js @@ -320,6 +320,93 @@ describe('RippleAPI', function() { 'prepare')); }); + it('preparePaymentChannelCreate', function() { + const localInstructions = _.defaults({ + maxFee: '0.000012' + }, instructions); + return this.api.preparePaymentChannelCreate( + address, requests.preparePaymentChannelCreate.normal, + localInstructions).then( + _.partial(checkResult, responses.preparePaymentChannelCreate.normal, + 'prepare')); + }); + + it('preparePaymentChannelCreate full', function() { + return this.api.preparePaymentChannelCreate( + address, requests.preparePaymentChannelCreate.full).then( + _.partial(checkResult, responses.preparePaymentChannelCreate.full, + 'prepare')); + }); + + it('preparePaymentChannelFund', function() { + const localInstructions = _.defaults({ + maxFee: '0.000012' + }, instructions); + return this.api.preparePaymentChannelFund( + address, requests.preparePaymentChannelFund.normal, + localInstructions).then( + _.partial(checkResult, responses.preparePaymentChannelFund.normal, + 'prepare')); + }); + + it('preparePaymentChannelFund full', function() { + return this.api.preparePaymentChannelFund( + address, requests.preparePaymentChannelFund.full).then( + _.partial(checkResult, responses.preparePaymentChannelFund.full, + 'prepare')); + }); + + it('preparePaymentChannelClaim', function() { + const localInstructions = _.defaults({ + maxFee: '0.000012' + }, instructions); + return this.api.preparePaymentChannelClaim( + address, requests.preparePaymentChannelClaim.normal, + localInstructions).then( + _.partial(checkResult, responses.preparePaymentChannelClaim.normal, + 'prepare')); + }); + + it('preparePaymentChannelClaim with renew', function() { + const localInstructions = _.defaults({ + maxFee: '0.000012' + }, instructions); + return this.api.preparePaymentChannelClaim( + address, requests.preparePaymentChannelClaim.renew, + localInstructions).then( + _.partial(checkResult, responses.preparePaymentChannelClaim.renew, + 'prepare')); + }); + + it('preparePaymentChannelClaim with close', function() { + const localInstructions = _.defaults({ + maxFee: '0.000012' + }, instructions); + return this.api.preparePaymentChannelClaim( + address, requests.preparePaymentChannelClaim.close, + localInstructions).then( + _.partial(checkResult, responses.preparePaymentChannelClaim.close, + 'prepare')); + }); + + it('throws on preparePaymentChannelClaim with renew and close', function() { + assert.throws(() => { + this.api.preparePaymentChannelClaim( + address, requests.preparePaymentChannelClaim.full).then( + _.partial(checkResult, responses.preparePaymentChannelClaim.full, + 'prepare')); + }, this.api.errors.ValidationError); + }); + + it('throws on preparePaymentChannelClaim with no signature', function() { + assert.throws(() => { + this.api.preparePaymentChannelClaim( + address, requests.preparePaymentChannelClaim.noSignature).then( + _.partial(checkResult, responses.preparePaymentChannelClaim.noSignature, + 'prepare')); + }, this.api.errors.ValidationError); + }); + it('sign', function() { const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'; const result = this.api.sign(requests.sign.normal.txJSON, secret); @@ -680,6 +767,33 @@ describe('RippleAPI', function() { 'getTransaction')); }); + it('getTransaction - PaymentChannelCreate', function() { + const hash = + '0E9CA3AB1053FC0C1CBAA75F636FE1EC92F118C7056BBEF5D63E4C116458A16D'; + return this.api.getTransaction(hash).then( + _.partial(checkResult, + responses.getTransaction.paymentChannelCreate, + 'getTransaction')); + }); + + it('getTransaction - PaymentChannelFund', function() { + const hash = + 'CD053D8867007A6A4ACB7A432605FE476D088DCB515AFFC886CF2B4EB6D2AE8B'; + return this.api.getTransaction(hash).then( + _.partial(checkResult, + responses.getTransaction.paymentChannelFund, + 'getTransaction')); + }); + + it('getTransaction - PaymentChannelClaim', function() { + const hash = + '81B9ECAE7195EB6E8034AEDF44D8415A7A803E14513FDBB34FA984AB37D59563'; + return this.api.getTransaction(hash).then( + _.partial(checkResult, + responses.getTransaction.paymentChannelClaim, + 'getTransaction')); + }); + it('getTransaction - no Meta', function() { const hash = 'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B'; diff --git a/test/fixtures/requests/index.js b/test/fixtures/requests/index.js index db44593e..89c96c11 100644 --- a/test/fixtures/requests/index.js +++ b/test/fixtures/requests/index.js @@ -36,6 +36,21 @@ module.exports = { normal: require('./prepare-escrow-cancellation'), memos: require('./prepare-escrow-cancellation-memos') }, + preparePaymentChannelCreate: { + normal: require('./prepare-payment-channel-create'), + full: require('./prepare-payment-channel-create-full') + }, + preparePaymentChannelFund: { + normal: require('./prepare-payment-channel-fund'), + full: require('./prepare-payment-channel-fund-full') + }, + preparePaymentChannelClaim: { + normal: require('./prepare-payment-channel-claim'), + full: require('./prepare-payment-channel-claim-full'), + close: require('./prepare-payment-channel-claim-close'), + renew: require('./prepare-payment-channel-claim-renew'), + noSignature: require('./prepare-payment-channel-claim-no-signature') + }, prepareTrustline: { simple: require('./prepare-trustline-simple'), complex: require('./prepare-trustline'), diff --git a/test/fixtures/requests/prepare-payment-channel-claim-close.json b/test/fixtures/requests/prepare-payment-channel-claim-close.json new file mode 100644 index 00000000..45edd5d3 --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-claim-close.json @@ -0,0 +1,8 @@ +{ + "channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "balance": "1", + "amount": "1", + "signature": "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", + "publicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + "close": true +} diff --git a/test/fixtures/requests/prepare-payment-channel-claim-full.json b/test/fixtures/requests/prepare-payment-channel-claim-full.json new file mode 100644 index 00000000..b3606043 --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-claim-full.json @@ -0,0 +1,9 @@ +{ + "channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "balance": "1", + "amount": "1", + "signature": "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", + "publicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + "renew": true, + "close": true +} diff --git a/test/fixtures/requests/prepare-payment-channel-claim-no-signature.json b/test/fixtures/requests/prepare-payment-channel-claim-no-signature.json new file mode 100644 index 00000000..418ee90a --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-claim-no-signature.json @@ -0,0 +1,6 @@ +{ + "channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "balance": "1", + "amount": "1", + "publicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A" +} diff --git a/test/fixtures/requests/prepare-payment-channel-claim-renew.json b/test/fixtures/requests/prepare-payment-channel-claim-renew.json new file mode 100644 index 00000000..247cf728 --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-claim-renew.json @@ -0,0 +1,8 @@ +{ + "channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "balance": "1", + "amount": "1", + "signature": "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", + "publicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + "renew": true +} diff --git a/test/fixtures/requests/prepare-payment-channel-claim.json b/test/fixtures/requests/prepare-payment-channel-claim.json new file mode 100644 index 00000000..ae83471e --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-claim.json @@ -0,0 +1,3 @@ +{ + "channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198" +} diff --git a/test/fixtures/requests/prepare-payment-channel-create-full.json b/test/fixtures/requests/prepare-payment-channel-create-full.json new file mode 100644 index 00000000..109e5a66 --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-create-full.json @@ -0,0 +1,9 @@ +{ + "amount": "1", + "destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "settleDelay": 86400, + "publicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + "cancelAfter": "2017-02-17T15:04:57Z", + "destinationTag": 23480, + "sourceTag": 11747 +} diff --git a/test/fixtures/requests/prepare-payment-channel-create.json b/test/fixtures/requests/prepare-payment-channel-create.json new file mode 100644 index 00000000..0ebc6183 --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-create.json @@ -0,0 +1,6 @@ +{ + "amount": "1", + "destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "settleDelay": 86400, + "publicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A" +} diff --git a/test/fixtures/requests/prepare-payment-channel-fund-full.json b/test/fixtures/requests/prepare-payment-channel-fund-full.json new file mode 100644 index 00000000..ee423611 --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-fund-full.json @@ -0,0 +1,5 @@ +{ + "channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "amount": "1", + "expiration": "2017-02-17T15:04:57Z" +} diff --git a/test/fixtures/requests/prepare-payment-channel-fund.json b/test/fixtures/requests/prepare-payment-channel-fund.json new file mode 100644 index 00000000..7edb66c9 --- /dev/null +++ b/test/fixtures/requests/prepare-payment-channel-fund.json @@ -0,0 +1,4 @@ +{ + "channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "amount": "1" +} diff --git a/test/fixtures/responses/get-transaction-payment-channel-claim.json b/test/fixtures/responses/get-transaction-payment-channel-claim.json new file mode 100644 index 00000000..3fe46372 --- /dev/null +++ b/test/fixtures/responses/get-transaction-payment-channel-claim.json @@ -0,0 +1,28 @@ +{ + "type": "paymentChannelClaim", + "address": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "sequence": 99, + "id": "81B9ECAE7195EB6E8034AEDF44D8415A7A803E14513FDBB34FA984AB37D59563", + "specification": { + "channel": "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1", + "balance": "0.801", + "publicKey": "EDE059A23CBE00BDD465910EBDA67C86BAD046FA52E1BBBB27159E31980BAFEFB9", + "signature": "5567FB8A27D8BF0C556D3D31D034476FC04F43846A6613EB4B1B64C396C833600BE251CE3104CF02DA0085B473E02BA0BA21F794FB1DC95DAD702F3EA761CA02" + }, + "outcome": { + "result": "tesSUCCESS", + "timestamp": "2017-03-09T14:09:51.000Z", + "fee": "0.000012", + "balanceChanges": { + "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa": [ + { + "currency": "XRP", + "value": "0.800988" + } + ] + }, + "orderbookChanges": {}, + "ledgerVersion": 786310, + "indexInLedger": 0 + } +} diff --git a/test/fixtures/responses/get-transaction-payment-channel-create.json b/test/fixtures/responses/get-transaction-payment-channel-create.json new file mode 100644 index 00000000..55d4d54f --- /dev/null +++ b/test/fixtures/responses/get-transaction-payment-channel-create.json @@ -0,0 +1,29 @@ +{ + "type": "paymentChannelCreate", + "address": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "sequence": 113, + "id": "0E9CA3AB1053FC0C1CBAA75F636FE1EC92F118C7056BBEF5D63E4C116458A16D", + "specification": { + "amount": "1", + "destination": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "sourceTag": 3444675312, + "publicKey": "EDE059A23CBE00BDD465910EBDA67C86BAD046FA52E1BBBB27159E31980BAFEFB9", + "settleDelay": 90000 + }, + "outcome": { + "result": "tesSUCCESS", + "timestamp": "2017-03-09T14:09:50.000Z", + "fee": "0.000012", + "balanceChanges": { + "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK": [ + { + "currency": "XRP", + "value": "-1.000012" + } + ] + }, + "orderbookChanges": {}, + "ledgerVersion": 786309, + "indexInLedger": 0 + } +} diff --git a/test/fixtures/responses/get-transaction-payment-channel-fund.json b/test/fixtures/responses/get-transaction-payment-channel-fund.json new file mode 100644 index 00000000..da5ed1c6 --- /dev/null +++ b/test/fixtures/responses/get-transaction-payment-channel-fund.json @@ -0,0 +1,26 @@ +{ + "type": "paymentChannelFund", + "address": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "sequence": 114, + "id": "CD053D8867007A6A4ACB7A432605FE476D088DCB515AFFC886CF2B4EB6D2AE8B", + "specification": { + "channel": "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1", + "amount": "1" + }, + "outcome": { + "result": "tesSUCCESS", + "timestamp": "2017-03-09T14:09:51.000Z", + "fee": "0.000012", + "balanceChanges": { + "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK": [ + { + "currency": "XRP", + "value": "-1.000012" + } + ] + }, + "orderbookChanges": {}, + "ledgerVersion": 786310, + "indexInLedger": 1 + } +} diff --git a/test/fixtures/responses/index.js b/test/fixtures/responses/index.js index d239d074..5f1cab0f 100644 --- a/test/fixtures/responses/index.js +++ b/test/fixtures/responses/index.js @@ -42,6 +42,12 @@ module.exports = { require('./get-transaction-escrow-execution.json'), escrowExecutionSimple: require('./get-transaction-escrow-execution-simple.json'), + paymentChannelCreate: + require('./get-transaction-payment-channel-create.json'), + paymentChannelFund: + require('./get-transaction-payment-channel-fund.json'), + paymentChannelClaim: + require('./get-transaction-payment-channel-claim.json'), amendment: require('./get-transaction-amendment.json'), feeUpdate: require('./get-transaction-fee-update.json') }, @@ -105,6 +111,19 @@ module.exports = { normal: require('./prepare-escrow-cancellation'), memos: require('./prepare-escrow-cancellation-memos') }, + preparePaymentChannelCreate: { + normal: require('./prepare-payment-channel-create'), + full: require('./prepare-payment-channel-create-full') + }, + preparePaymentChannelFund: { + normal: require('./prepare-payment-channel-fund'), + full: require('./prepare-payment-channel-fund-full') + }, + preparePaymentChannelClaim: { + normal: require('./prepare-payment-channel-claim'), + renew: require('./prepare-payment-channel-claim-renew'), + close: require('./prepare-payment-channel-claim-close') + }, prepareTrustline: { simple: require('./prepare-trustline-simple.json'), frozen: require('./prepare-trustline-frozen.json'), diff --git a/test/fixtures/responses/prepare-payment-channel-claim-close.json b/test/fixtures/responses/prepare-payment-channel-claim-close.json new file mode 100644 index 00000000..0dc2c8c9 --- /dev/null +++ b/test/fixtures/responses/prepare-payment-channel-claim-close.json @@ -0,0 +1,8 @@ +{ + "txJSON": "{\"Channel\":\"C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198\",\"Balance\":\"1000000\",\"Amount\":\"1000000\",\"Signature\":\"30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B\",\"PublicKey\":\"32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A\",\"Fee\":\"12\",\"Sequence\":23,\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"TransactionType\":\"PaymentChannelClaim\",\"Flags\":2147614720,\"LastLedgerSequence\":8820051,\"Fee\":\"12\"}", + "instructions": { + "fee": "0.000012", + "sequence": 23, + "maxLedgerVersion": 8820051 + } +} diff --git a/test/fixtures/responses/prepare-payment-channel-claim-renew.json b/test/fixtures/responses/prepare-payment-channel-claim-renew.json new file mode 100644 index 00000000..f6211110 --- /dev/null +++ b/test/fixtures/responses/prepare-payment-channel-claim-renew.json @@ -0,0 +1,8 @@ +{ + "txJSON": "{\"Channel\":\"C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198\",\"Balance\":\"1000000\",\"Amount\":\"1000000\",\"Signature\":\"30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B\",\"PublicKey\":\"32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A\",\"Fee\":\"12\",\"Sequence\":23,\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"TransactionType\":\"PaymentChannelClaim\",\"Flags\":2147549184,\"LastLedgerSequence\":8820051,\"Fee\":\"12\"}", + "instructions": { + "fee": "0.000012", + "sequence": 23, + "maxLedgerVersion": 8820051 + } +} diff --git a/test/fixtures/responses/prepare-payment-channel-claim.json b/test/fixtures/responses/prepare-payment-channel-claim.json new file mode 100644 index 00000000..91058173 --- /dev/null +++ b/test/fixtures/responses/prepare-payment-channel-claim.json @@ -0,0 +1,8 @@ +{ + "txJSON": "{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"TransactionType\":\"PaymentChannelClaim\",\"Channel\":\"C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198\",\"Flags\":2147483648,\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}", + "instructions": { + "fee": "0.000012", + "sequence": 23, + "maxLedgerVersion": 8820051 + } +} diff --git a/test/fixtures/responses/prepare-payment-channel-create-full.json b/test/fixtures/responses/prepare-payment-channel-create-full.json new file mode 100644 index 00000000..1cd38c34 --- /dev/null +++ b/test/fixtures/responses/prepare-payment-channel-create-full.json @@ -0,0 +1,8 @@ +{ + "txJSON":"{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"TransactionType\":\"PaymentChannelCreate\",\"Amount\":\"1000000\",\"Destination\":\"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW\",\"SettleDelay\":86400,\"PublicKey\":\"32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A\",\"DestinationTag\":23480,\"SourceTag\":11747,\"CancelAfter\":540659097,\"Flags\":2147483648,\"LastLedgerSequence\":8819954,\"Fee\":\"12\",\"Sequence\":23}", + "instructions": { + "fee": "0.000012", + "sequence": 23, + "maxLedgerVersion": 8819954 + } +} diff --git a/test/fixtures/responses/prepare-payment-channel-create.json b/test/fixtures/responses/prepare-payment-channel-create.json new file mode 100644 index 00000000..7236b7ae --- /dev/null +++ b/test/fixtures/responses/prepare-payment-channel-create.json @@ -0,0 +1,8 @@ +{ + "txJSON":"{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"TransactionType\":\"PaymentChannelCreate\",\"Amount\":\"1000000\",\"Destination\":\"rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW\",\"SettleDelay\":86400,\"PublicKey\":\"32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A\",\"Flags\":2147483648,\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}", + "instructions": { + "fee": "0.000012", + "sequence": 23, + "maxLedgerVersion": 8820051 + } +} diff --git a/test/fixtures/responses/prepare-payment-channel-fund-full.json b/test/fixtures/responses/prepare-payment-channel-fund-full.json new file mode 100644 index 00000000..fa6b1686 --- /dev/null +++ b/test/fixtures/responses/prepare-payment-channel-fund-full.json @@ -0,0 +1,8 @@ +{ + "txJSON":"{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"TransactionType\":\"PaymentChannelFund\",\"Channel\":\"C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198\",\"Amount\":\"1000000\",\"Expiration\":540659097,\"Flags\":2147483648,\"LastLedgerSequence\":8819954,\"Fee\":\"12\",\"Sequence\":23}", + "instructions": { + "fee": "0.000012", + "sequence": 23, + "maxLedgerVersion": 8819954 + } +} diff --git a/test/fixtures/responses/prepare-payment-channel-fund.json b/test/fixtures/responses/prepare-payment-channel-fund.json new file mode 100644 index 00000000..9c959fd1 --- /dev/null +++ b/test/fixtures/responses/prepare-payment-channel-fund.json @@ -0,0 +1,8 @@ +{ + "txJSON":"{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"TransactionType\":\"PaymentChannelFund\",\"Channel\":\"C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198\",\"Amount\":\"1000000\",\"Flags\":2147483648,\"LastLedgerSequence\":8820051,\"Fee\":\"12\",\"Sequence\":23}", + "instructions": { + "fee": "0.000012", + "sequence": 23, + "maxLedgerVersion": 8820051 + } +} diff --git a/test/fixtures/rippled/index.js b/test/fixtures/rippled/index.js index a8f78b13..3959f627 100644 --- a/test/fixtures/rippled/index.js +++ b/test/fixtures/rippled/index.js @@ -70,6 +70,9 @@ module.exports = { EscrowExecution: require('./tx/escrow-execution.json'), EscrowExecutionSimple: require('./tx/escrow-execution-simple.json'), + PaymentChannelCreate: require('./tx/payment-channel-create.json'), + PaymentChannelFund: require('./tx/payment-channel-fund.json'), + PaymentChannelClaim: require('./tx/payment-channel-claim.json'), Unrecognized: require('./tx/unrecognized.json'), NoMeta: require('./tx/no-meta.json'), LedgerZero: require('./tx/ledger-zero.json'), diff --git a/test/fixtures/rippled/tx/payment-channel-claim.json b/test/fixtures/rippled/tx/payment-channel-claim.json new file mode 100644 index 00000000..06b80290 --- /dev/null +++ b/test/fixtures/rippled/tx/payment-channel-claim.json @@ -0,0 +1,70 @@ +{ + "result": { + "Account": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "Balance": "801000", + "Channel": "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1", + "Fee": "12", + "Flags": 2147483648, + "LastLedgerSequence": 786312, + "PublicKey": "EDE059A23CBE00BDD465910EBDA67C86BAD046FA52E1BBBB27159E31980BAFEFB9", + "Sequence": 99, + "Signature": "5567FB8A27D8BF0C556D3D31D034476FC04F43846A6613EB4B1B64C396C833600BE251CE3104CF02DA0085B473E02BA0BA21F794FB1DC95DAD702F3EA761CA02", + "SigningPubKey": "030697E72D738538BBE149CC3E85AA43FE836B5B34810F6370D6BB7D6D4938CEE6", + "TransactionType": "PaymentChannelClaim", + "TxnSignature": "3044022045EF38CCBE52D81D9A4060DD7203D626BC51B4779246FCFB71E4D0300D774DE002201A12A93081CF8539AF5EB4FB33F173729B499B5D5CD5EB66BD028A35F2ECAFEC", + "date": 542383791, + "hash": "81B9ECAE7195EB6E8034AEDF44D8415A7A803E14513FDBB34FA984AB37D59563", + "inLedger": 786310, + "ledger_index": 786310, + "meta": { + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "Amount": "1000000", + "Balance": "801000", + "Destination": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "Flags": 0, + "OwnerNode": "0000000000000002", + "PublicKey": "EDE059A23CBE00BDD465910EBDA67C86BAD046FA52E1BBBB27159E31980BAFEFB9", + "SettleDelay": 90000, + "SourceTag": 3444675312 + }, + "LedgerEntryType": "PayChannel", + "LedgerIndex": "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1", + "PreviousFields": { + "Balance": "0" + }, + "PreviousTxnID": "0E9CA3AB1053FC0C1CBAA75F636FE1EC92F118C7056BBEF5D63E4C116458A16D", + "PreviousTxnLgrSeq": 786309 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "Balance": "9685416812", + "Flags": 0, + "OwnerCount": 81, + "Sequence": 100 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "659611ECC02612E5352D194628C2133D4983C4815B564F75722DA9327B6434D2", + "PreviousFields": { + "Balance": "9684615824", + "Sequence": 99 + }, + "PreviousTxnID": "9502119B8457ADF72DC137EB44DE897D7CD8583CE1C9541CA9A4FD27B4149FBD", + "PreviousTxnLgrSeq": 786309 + } + } + ], + "TransactionIndex": 0, + "TransactionResult": "tesSUCCESS" + }, + "validated": true + }, + "status": "success", + "type": "response" +} diff --git a/test/fixtures/rippled/tx/payment-channel-create.json b/test/fixtures/rippled/tx/payment-channel-create.json new file mode 100644 index 00000000..f74a9712 --- /dev/null +++ b/test/fixtures/rippled/tx/payment-channel-create.json @@ -0,0 +1,86 @@ +{ + "id": 0, + "result": { + "Account": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "Amount": "1000000", + "Destination": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "Fee": "12", + "Flags": 2147483648, + "LastLedgerSequence": 786310, + "PublicKey": "EDE059A23CBE00BDD465910EBDA67C86BAD046FA52E1BBBB27159E31980BAFEFB9", + "Sequence": 113, + "SettleDelay": 90000, + "SigningPubKey": "0243D321B6585B7F6EB5B6AEA6B98C5EAD6FE09C09F79722640029538F03F083E5", + "SourceTag": 3444675312, + "TransactionType": "PaymentChannelCreate", + "TxnSignature": "3045022100ECA04F35A18F74E24029060B51AC2AEEECCEB8663A3029DD2966E5F99CB8606F0220581CB2B7C5D8A32717991396B9FD77734CA47CF02654938F06509450B4772052", + "date": 542383790, + "hash": "0E9CA3AB1053FC0C1CBAA75F636FE1EC92F118C7056BBEF5D63E4C116458A16D", + "inLedger": 786309, + "ledger_index": 786309, + "meta": { + "AffectedNodes": [ + { + "CreatedNode": { + "LedgerEntryType": "PayChannel", + "LedgerIndex": "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1", + "NewFields": { + "Account": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "Amount": "1000000", + "Destination": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "OwnerNode": "0000000000000002", + "PublicKey": "EDE059A23CBE00BDD465910EBDA67C86BAD046FA52E1BBBB27159E31980BAFEFB9", + "SettleDelay": 90000, + "SourceTag": 3444675312 + } + } + }, + { + "ModifiedNode": { + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "659611ECC02612E5352D194628C2133D4983C4815B564F75722DA9327B6434D2", + "PreviousTxnID": "450C1D132C21F3CED037F3442075AD0339B5A02EA8BC21D4DD6A13ED2C3A3DD6", + "PreviousTxnLgrSeq": 786294 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "Balance": "9583993644", + "Flags": 0, + "OwnerCount": 91, + "Sequence": 114 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "C3C855510E420246A61813C11A999F1246AD3C11E1020AB097BE81877CEA159C", + "PreviousFields": { + "Balance": "9584993656", + "OwnerCount": 90, + "Sequence": 113 + }, + "PreviousTxnID": "450C1D132C21F3CED037F3442075AD0339B5A02EA8BC21D4DD6A13ED2C3A3DD6", + "PreviousTxnLgrSeq": 786294 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Flags": 0, + "IndexPrevious": "0000000000000001", + "Owner": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "RootIndex": "E0E23E1C6AB66761C95738D50927A2B5C0EC62E78E58A591EF285219F9492F13" + }, + "LedgerEntryType": "DirectoryNode", + "LedgerIndex": "DFF52A9A7C30C3785111879DF606B254CB6E9FFA2271BFFA3406EE2A65929D67" + } + } + ], + "TransactionIndex": 0, + "TransactionResult": "tesSUCCESS" + }, + "validated": true + }, + "status": "success", + "type": "response" +} diff --git a/test/fixtures/rippled/tx/payment-channel-fund.json b/test/fixtures/rippled/tx/payment-channel-fund.json new file mode 100644 index 00000000..2e8a8900 --- /dev/null +++ b/test/fixtures/rippled/tx/payment-channel-fund.json @@ -0,0 +1,69 @@ +{ + "id": 0, + "result": { + "Account": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "Amount": "1000000", + "Channel": "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1", + "Fee": "12", + "Flags": 2147483648, + "LastLedgerSequence": 786312, + "Sequence": 114, + "SigningPubKey": "0243D321B6585B7F6EB5B6AEA6B98C5EAD6FE09C09F79722640029538F03F083E5", + "TransactionType": "PaymentChannelFund", + "TxnSignature": "304402203F4D2DD537C4EF4CDC2C525190698715A2188733681DB6205C9A6FCBEA3C89E202202526B40DCC025B5D12CD82789D4E37FB16918FFA94CF91113CFD9ADCF9D185A1", + "date": 542383791, + "hash": "CD053D8867007A6A4ACB7A432605FE476D088DCB515AFFC886CF2B4EB6D2AE8B", + "inLedger": 786310, + "ledger_index": 786310, + "meta": { + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "Amount": "2000000", + "Balance": "801000", + "Destination": "rBmNDZ7vbTCwakKXsX3pDAwDdQuxM7yBRa", + "Flags": 0, + "OwnerNode": "0000000000000002", + "PublicKey": "EDE059A23CBE00BDD465910EBDA67C86BAD046FA52E1BBBB27159E31980BAFEFB9", + "SettleDelay": 90000, + "SourceTag": 3444675312 + }, + "LedgerEntryType": "PayChannel", + "LedgerIndex": "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1", + "PreviousFields": { + "Amount": "1000000" + }, + "PreviousTxnID": "81B9ECAE7195EB6E8034AEDF44D8415A7A803E14513FDBB34FA984AB37D59563", + "PreviousTxnLgrSeq": 786310 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rfAuMkVuZQnQhvdMcUKg4ndBb9SPDhzNmK", + "Balance": "9582993632", + "Flags": 0, + "OwnerCount": 91, + "Sequence": 115 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "C3C855510E420246A61813C11A999F1246AD3C11E1020AB097BE81877CEA159C", + "PreviousFields": { + "Balance": "9583993644", + "Sequence": 114 + }, + "PreviousTxnID": "9502119B8457ADF72DC137EB44DE897D7CD8583CE1C9541CA9A4FD27B4149FBD", + "PreviousTxnLgrSeq": 786309 + } + } + ], + "TransactionIndex": 1, + "TransactionResult": "tesSUCCESS" + }, + "validated": true + }, + "status": "success", + "type": "response" +} diff --git a/test/mock-rippled.js b/test/mock-rippled.js index 570fe67d..cb4eb8a0 100644 --- a/test/mock-rippled.js +++ b/test/mock-rippled.js @@ -284,6 +284,15 @@ module.exports = function createMockRippled(port) { 'CC5277137B3F25EE8B86259C83CB0EAADE818505E4E9BCBF19B1AC6FD1369931') { conn.send(createResponse(request, fixtures.tx.EscrowExecutionSimple)); + } else if (request.transaction === + '0E9CA3AB1053FC0C1CBAA75F636FE1EC92F118C7056BBEF5D63E4C116458A16D') { + conn.send(createResponse(request, fixtures.tx.PaymentChannelCreate)); + } else if (request.transaction === + 'CD053D8867007A6A4ACB7A432605FE476D088DCB515AFFC886CF2B4EB6D2AE8B') { + conn.send(createResponse(request, fixtures.tx.PaymentChannelFund)); + } else if (request.transaction === + '81B9ECAE7195EB6E8034AEDF44D8415A7A803E14513FDBB34FA984AB37D59563') { + conn.send(createResponse(request, fixtures.tx.PaymentChannelClaim)); } else if (request.transaction === 'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA11') { conn.send(createResponse(request, fixtures.tx.Unrecognized));