mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
Add support for AccountDelete (#1120)
https://xrpl.org/accountdelete.html
This commit is contained in:
@@ -4511,7 +4511,7 @@ Prepare a transaction. The prepared transaction must subsequently be [signed](#s
|
||||
|
||||
This method works with any of [the transaction types supported by rippled](https://developers.ripple.com/transaction-types.html).
|
||||
|
||||
Notably, this is the preferred method for preparing a `DepositPreauth` transaction (added in rippled 1.1.0).
|
||||
Notably, this is the preferred method for preparing `DepositPreauth` or `AccountDelete` transactions.
|
||||
|
||||
### Parameters
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Prepare a transaction. The prepared transaction must subsequently be [signed](#s
|
||||
|
||||
This method works with any of [the transaction types supported by rippled](https://developers.ripple.com/transaction-types.html).
|
||||
|
||||
Notably, this is the preferred method for preparing a `DepositPreauth` transaction (added in rippled 1.1.0).
|
||||
Notably, this is the preferred method for preparing `DepositPreauth` or `AccountDelete` transactions.
|
||||
|
||||
### Parameters
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ function loadSchemas() {
|
||||
require('./schemas/specifications/check-cash.json'),
|
||||
require('./schemas/specifications/check-cancel.json'),
|
||||
require('./schemas/specifications/trustline.json'),
|
||||
require('./schemas/specifications/deposit-preauth.json'),
|
||||
require('./schemas/specifications/account-delete.json'),
|
||||
require('./schemas/output/sign.json'),
|
||||
require('./schemas/output/submit.json'),
|
||||
require('./schemas/output/get-account-info.json'),
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
"paymentChannelClaim",
|
||||
"checkCreate",
|
||||
"checkCancel",
|
||||
"checkCash"
|
||||
"checkCash",
|
||||
"depositPreauth",
|
||||
"accountDelete"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -208,6 +208,30 @@
|
||||
"$ref": "paymentChannelClaim"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"depositPreauth"
|
||||
]
|
||||
},
|
||||
"specification": {
|
||||
"$ref": "depositPreauth"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"accountDelete"
|
||||
]
|
||||
},
|
||||
"specification": {
|
||||
"$ref": "accountDelete"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
29
src/common/schemas/specifications/account-delete.json
Normal file
29
src/common/schemas/specifications/account-delete.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "accountDelete",
|
||||
"link": "account-delete",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"destination": {
|
||||
"$ref": "address",
|
||||
"description": "Address of an account to receive any leftover XRP after deleting the sending account. Must be a funded account in the ledger, and must not be the sending account."
|
||||
},
|
||||
"destinationTag": {
|
||||
"$ref": "tag",
|
||||
"description": "(Optional) Arbitrary destination tag that identifies a hosted recipient or other information for the recipient of the deleted account's leftover XRP."
|
||||
},
|
||||
"destinationXAddress": {
|
||||
"$ref": "address",
|
||||
"description": "X-address of an account to receive any leftover XRP after deleting the sending account. Must be a funded account in the ledger, and must not be the sending account."
|
||||
}
|
||||
},
|
||||
"anyOf": [
|
||||
{
|
||||
"required": ["destination"]
|
||||
},
|
||||
{
|
||||
"required": ["destinationXAddress"]
|
||||
}
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
21
src/common/schemas/specifications/deposit-preauth.json
Normal file
21
src/common/schemas/specifications/deposit-preauth.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "depositPreauth",
|
||||
"link": "deposit-preauth",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"authorize": {
|
||||
"$ref": "address",
|
||||
"description": "Address of the account that can cash the check."
|
||||
},
|
||||
"unauthorize": {
|
||||
"$ref": "address",
|
||||
"description": "Address of the account that can cash the check."
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{"required": ["authorize"]},
|
||||
{"required": ["unauthorize"]}
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
34
src/ledger/parse/account-delete.ts
Normal file
34
src/ledger/parse/account-delete.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import * as assert from 'assert'
|
||||
import {removeUndefined} from '../../common'
|
||||
import {classicAddressToXAddress} from 'ripple-address-codec'
|
||||
|
||||
export type FormattedAccountDelete = {
|
||||
// account (address) of an account to receive any leftover XRP after deleting the sending account.
|
||||
// Must be a funded account in the ledger, and must not be the sending account.
|
||||
destination: string
|
||||
|
||||
// (Optional) Arbitrary destination tag that identifies a hosted recipient or other information
|
||||
// for the recipient of the deleted account's leftover XRP. NB: Ensure that the hosted recipient is
|
||||
// able to account for AccountDelete transactions; if not, your balance may not be properly credited.
|
||||
destinationTag?: number
|
||||
|
||||
// X-address of an account to receive any leftover XRP after deleting the sending account.
|
||||
// Must be a funded account in the ledger, and must not be the sending account.
|
||||
destinationXAddress: string
|
||||
}
|
||||
|
||||
function parseAccountDelete(tx: any): FormattedAccountDelete {
|
||||
assert.ok(tx.TransactionType === 'AccountDelete')
|
||||
|
||||
return removeUndefined({
|
||||
destination: tx.Destination,
|
||||
destinationTag: tx.DestinationTag,
|
||||
destinationXAddress: classicAddressToXAddress(
|
||||
tx.Destination,
|
||||
tx.DestinationTag === undefined ? false : tx.DestinationTag,
|
||||
false
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
export default parseAccountDelete
|
||||
@@ -1,27 +1,31 @@
|
||||
import {parseOutcome} from './utils'
|
||||
import {removeUndefined} from '../../common'
|
||||
import parsePayment from './payment'
|
||||
import parseTrustline from './trustline'
|
||||
import parseOrder from './order'
|
||||
import parseOrderCancellation from './cancellation'
|
||||
|
||||
import parseSettings from './settings'
|
||||
import parseAccountDelete from './account-delete'
|
||||
import parseCheckCancel from './check-cancel'
|
||||
import parseCheckCash from './check-cash'
|
||||
import parseCheckCreate from './check-create'
|
||||
import parseDepositPreauth from './deposit-preauth'
|
||||
import parseEscrowCancellation from './escrow-cancellation'
|
||||
import parseEscrowCreation from './escrow-creation'
|
||||
import parseEscrowExecution from './escrow-execution'
|
||||
import parseEscrowCancellation from './escrow-cancellation'
|
||||
import parseCheckCreate from './check-create'
|
||||
import parseCheckCash from './check-cash'
|
||||
import parseCheckCancel from './check-cancel'
|
||||
import parseDepositPreauth from './deposit-preauth'
|
||||
import parseOrderCancellation from './cancellation'
|
||||
import parseOrder from './order'
|
||||
import parsePayment from './payment'
|
||||
import parsePaymentChannelClaim from './payment-channel-claim'
|
||||
import parsePaymentChannelCreate from './payment-channel-create'
|
||||
import parsePaymentChannelFund from './payment-channel-fund'
|
||||
import parsePaymentChannelClaim from './payment-channel-claim'
|
||||
import parseFeeUpdate from './fee-update'
|
||||
import parseAmendment from './amendment'
|
||||
import parseTrustline from './trustline'
|
||||
|
||||
import parseAmendment from './amendment' // pseudo-transaction
|
||||
import parseFeeUpdate from './fee-update' // pseudo-transaction
|
||||
|
||||
function parseTransactionType(type) {
|
||||
// Ordering matches https://developers.ripple.com/transaction-types.html
|
||||
const mapping = {
|
||||
AccountSet: 'settings',
|
||||
AccountDelete: 'accountDelete',
|
||||
CheckCancel: 'checkCancel',
|
||||
CheckCash: 'checkCash',
|
||||
CheckCreate: 'checkCreate',
|
||||
@@ -49,23 +53,25 @@ function parseTransactionType(type) {
|
||||
function parseTransaction(tx: any, includeRawTransaction: boolean): any {
|
||||
const type = parseTransactionType(tx.TransactionType)
|
||||
const mapping = {
|
||||
payment: parsePayment,
|
||||
trustline: parseTrustline,
|
||||
order: parseOrder,
|
||||
orderCancellation: parseOrderCancellation,
|
||||
settings: parseSettings,
|
||||
accountDelete: parseAccountDelete,
|
||||
checkCancel: parseCheckCancel,
|
||||
checkCash: parseCheckCash,
|
||||
checkCreate: parseCheckCreate,
|
||||
depositPreauth: parseDepositPreauth,
|
||||
escrowCancellation: parseEscrowCancellation,
|
||||
escrowCreation: parseEscrowCreation,
|
||||
escrowExecution: parseEscrowExecution,
|
||||
escrowCancellation: parseEscrowCancellation,
|
||||
checkCreate: parseCheckCreate,
|
||||
checkCash: parseCheckCash,
|
||||
checkCancel: parseCheckCancel,
|
||||
depositPreauth: parseDepositPreauth,
|
||||
orderCancellation: parseOrderCancellation,
|
||||
order: parseOrder,
|
||||
payment: parsePayment,
|
||||
paymentChannelClaim: parsePaymentChannelClaim,
|
||||
paymentChannelCreate: parsePaymentChannelCreate,
|
||||
paymentChannelFund: parsePaymentChannelFund,
|
||||
paymentChannelClaim: parsePaymentChannelClaim,
|
||||
feeUpdate: parseFeeUpdate,
|
||||
amendment: parseAmendment
|
||||
trustline: parseTrustline,
|
||||
|
||||
amendment: parseAmendment, // pseudo-transaction
|
||||
feeUpdate: parseFeeUpdate // pseudo-transaction
|
||||
}
|
||||
const parser: Function = mapping[type]
|
||||
|
||||
|
||||
@@ -354,6 +354,16 @@ export default <TestSuite>{
|
||||
)
|
||||
},
|
||||
|
||||
'AccountDelete': async (api, address) => {
|
||||
const hash = 'EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9'
|
||||
const response = await api.getTransaction(hash)
|
||||
assertResultMatch(
|
||||
response,
|
||||
RESPONSE_FIXTURES.accountDelete,
|
||||
'getTransaction'
|
||||
)
|
||||
},
|
||||
|
||||
'no Meta': async (api, address) => {
|
||||
const hash =
|
||||
'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA1B'
|
||||
|
||||
@@ -745,6 +745,33 @@ export default <TestSuite>{
|
||||
return assertResultMatch(response, expected, 'prepare')
|
||||
},
|
||||
|
||||
'AccountDelete': async (api, address) => {
|
||||
const localInstructions = {
|
||||
...instructionsWithMaxLedgerVersionOffset,
|
||||
maxFee: '5.0' // 5 XRP fee for AccountDelete
|
||||
}
|
||||
|
||||
const txJSON = {
|
||||
TransactionType: 'AccountDelete',
|
||||
Account: address,
|
||||
Destination: 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe'
|
||||
}
|
||||
|
||||
const response = await api.prepareTransaction(txJSON, localInstructions)
|
||||
const expected = {
|
||||
txJSON:
|
||||
'{"TransactionType":"AccountDelete","Account":"' +
|
||||
address +
|
||||
'","Destination":"rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}',
|
||||
instructions: {
|
||||
fee: '0.000012',
|
||||
sequence: 23,
|
||||
maxLedgerVersion: 8820051
|
||||
}
|
||||
}
|
||||
return assertResultMatch(response, expected, 'prepare')
|
||||
},
|
||||
|
||||
// prepareTransaction - Payment
|
||||
'Payment - normal': async (api, address) => {
|
||||
const localInstructions = {
|
||||
|
||||
@@ -212,7 +212,7 @@ export default <TestSuite>{
|
||||
) => {
|
||||
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
|
||||
const request = {
|
||||
// TODO: This fails when address is X-Address
|
||||
// TODO: This fails when address is X-address
|
||||
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"726970706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1.2","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
|
||||
instructions: {
|
||||
fee: '0.0000012',
|
||||
@@ -232,7 +232,7 @@ export default <TestSuite>{
|
||||
) => {
|
||||
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
|
||||
const request = {
|
||||
// TODO: This fails when address is X-Address
|
||||
// TODO: This fails when address is X-address
|
||||
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"726970706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1123456.7","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
|
||||
instructions: {
|
||||
fee: '1.1234567',
|
||||
@@ -289,7 +289,7 @@ export default <TestSuite>{
|
||||
api._maxFeeXRP = '2.1'
|
||||
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
|
||||
const request = {
|
||||
// TODO: This fails when address is X-Address
|
||||
// TODO: This fails when address is X-address
|
||||
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"726970706C652E636F6D","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
|
||||
instructions: {
|
||||
fee: '2.01',
|
||||
|
||||
32
test/fixtures/responses/get-transaction-account-delete.json
vendored
Normal file
32
test/fixtures/responses/get-transaction-account-delete.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"type": "accountDelete",
|
||||
"address": "rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv",
|
||||
"sequence": 3227049,
|
||||
"id": "EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9",
|
||||
"specification": {
|
||||
"destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
|
||||
"destinationXAddress": "XV5kHfQmzDQjbFNv4jX3FX9Y7ig5QhpKGEFCq4mdLfhdxMq"
|
||||
},
|
||||
"outcome": {
|
||||
"result": "tesSUCCESS",
|
||||
"timestamp": "2019-12-17T09:16:51.000Z",
|
||||
"fee": "5",
|
||||
"balanceChanges": {
|
||||
"rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv": [
|
||||
{
|
||||
"currency": "XRP",
|
||||
"value": "-10000"
|
||||
}
|
||||
],
|
||||
"rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe": [
|
||||
{
|
||||
"currency": "XRP",
|
||||
"value": "9995"
|
||||
}
|
||||
]
|
||||
},
|
||||
"orderbookChanges": {},
|
||||
"ledgerVersion": 3232071,
|
||||
"indexInLedger": 0
|
||||
}
|
||||
}
|
||||
3
test/fixtures/responses/index.js
vendored
3
test/fixtures/responses/index.js
vendored
@@ -67,7 +67,8 @@ module.exports = {
|
||||
paymentChannelClaim:
|
||||
require('./get-transaction-payment-channel-claim.json'),
|
||||
amendment: require('./get-transaction-amendment.json'),
|
||||
feeUpdate: require('./get-transaction-fee-update.json')
|
||||
feeUpdate: require('./get-transaction-fee-update.json'),
|
||||
accountDelete: require('./get-transaction-account-delete.json')
|
||||
},
|
||||
getTransactions: {
|
||||
normal: require('./get-transactions.json'),
|
||||
|
||||
3
test/fixtures/rippled/index.js
vendored
3
test/fixtures/rippled/index.js
vendored
@@ -99,6 +99,7 @@ module.exports = {
|
||||
NoMeta: require('./tx/no-meta.json'),
|
||||
LedgerZero: require('./tx/ledger-zero.json'),
|
||||
Amendment: require('./tx/amendment.json'),
|
||||
SetFee: require('./tx/set-fee.json')
|
||||
SetFee: require('./tx/set-fee.json'),
|
||||
AccountDelete: require('./tx/account-delete.json')
|
||||
}
|
||||
};
|
||||
|
||||
66
test/fixtures/rippled/tx/account-delete.json
vendored
Normal file
66
test/fixtures/rippled/tx/account-delete.json
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"id": 0,
|
||||
"result": {
|
||||
"Account": "rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv",
|
||||
"Destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
|
||||
"Fee": "5000000",
|
||||
"Flags": 2147483648,
|
||||
"LastLedgerSequence": 3232818,
|
||||
"Sequence": 3227049,
|
||||
"SigningPubKey": "022E0DBF14BC4CFF96BC839557EE6F12F6DA45DCD917376F805E65D1B1C60A8CE6",
|
||||
"TransactionType": "AccountDelete",
|
||||
"TxnSignature": "304402207BDBE1B71C8BD00363905817C9373880CE9E8F0080623D457495E2B760BBBEE402202EDEB977D1ED865C1EAB88FE28581E3F8A672097B8BB0956E977C6EC87CA668C",
|
||||
"date": 629889411,
|
||||
"hash": "EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9",
|
||||
"inLedger": 3232071,
|
||||
"ledger_index": 3232071,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"DeletedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rM5qup5BYDLMXaR5KU1hiC9HhFMuBVrnKv",
|
||||
"Balance": "0",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"PreviousTxnID": "2737BEDDDA1D7FB523CFB84B891216331CC4CC999349828D81C6C727A1115A44",
|
||||
"PreviousTxnLgrSeq": 3227049,
|
||||
"Sequence": 3227050
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "08EBF94D7BB527442E0B51F533B902DDCFBD423D8E95FAE752BE7876A29E875B",
|
||||
"PreviousFields": {
|
||||
"Balance": "10000000000",
|
||||
"Sequence": 3227049
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
|
||||
"Balance": "99991026734967448",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 2978
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "31CCE9D28412FF973E9AB6D0FA219BACF19687D9A2456A0C2ABC3280E9D47E37",
|
||||
"PreviousFields": {
|
||||
"Balance": "99991016739967448"
|
||||
},
|
||||
"PreviousTxnID": "2737BEDDDA1D7FB523CFB84B891216331CC4CC999349828D81C6C727A1115A44",
|
||||
"PreviousTxnLgrSeq": 3227049
|
||||
}
|
||||
}
|
||||
],
|
||||
"DeliveredAmount": "9995000000",
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS",
|
||||
"delivered_amount": "9995000000"
|
||||
},
|
||||
"validated": true
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
@@ -524,6 +524,11 @@ export function createMockRippled(port) {
|
||||
'81B9ECAE7195EB6E8034AEDF44D8415A7A803E14513FDBB34FA984AB37D59563'
|
||||
) {
|
||||
conn.send(createResponse(request, fixtures.tx.PaymentChannelClaim))
|
||||
} else if (
|
||||
request.transaction ===
|
||||
'EC2AB14028DC84DE525470AB4DAAA46358B50A8662C63804BFF38244731C0CB9'
|
||||
) {
|
||||
conn.send(createResponse(request, fixtures.tx.AccountDelete))
|
||||
} else if (
|
||||
request.transaction ===
|
||||
'AFB3ADF22F3C605E23FAEFAA185F3BD763C4692CAC490D9819D117CD33BFAA11'
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('RippleAPI [Test Runner]', function() {
|
||||
})
|
||||
// Run each test with the newer, x-address style.
|
||||
if (!config.skipXAddress) {
|
||||
describe(`[X-Address]`, () => {
|
||||
describe(`[X-address]`, () => {
|
||||
for (const [testName, fn] of tests) {
|
||||
it(testName, function() {
|
||||
return fn(this.api, addresses.ACCOUNT_X)
|
||||
|
||||
@@ -33,7 +33,7 @@ interface LoadedTestSuite {
|
||||
name: string
|
||||
tests: [string, TestFn][]
|
||||
config: {
|
||||
/** Set to true to skip re-running tests with an X-Address. */
|
||||
/** Set to true to skip re-running tests with an X-address. */
|
||||
skipXAddress?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user