mirror of
https://github.com/Xahau/xahau.js.git
synced 2026-06-03 00:36:42 +00:00
refactor: simplify submit transaction methods (#1725)
* To simplify submit transaction requests by having only one version of them that supports both signed/unsigned transactions, the signed versions of them (submitSigned(), submitSignedReliable()) are deleted. * Their signed logic is merged into submit() and submitAndWait() (renamed from submitReliable()). * Change order of submit method params to be consistent. * Add a SubmitOptions method param to include options for wallet to sign a transaction, and booleans to autofill/failHard a transaction.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -93,9 +93,7 @@ import {
|
||||
getBalances,
|
||||
getXrpBalance,
|
||||
submit,
|
||||
submitSigned,
|
||||
submitReliable,
|
||||
submitSignedReliable,
|
||||
submitAndWait,
|
||||
} from '../sugar'
|
||||
import fundWallet from '../wallet/fundWallet'
|
||||
|
||||
@@ -596,15 +594,7 @@ class Client extends EventEmitter {
|
||||
/**
|
||||
* @category Core
|
||||
*/
|
||||
public submitSigned = submitSigned
|
||||
/**
|
||||
* @category Core
|
||||
*/
|
||||
public submitReliable = submitReliable
|
||||
/**
|
||||
* @category Core
|
||||
*/
|
||||
public submitSignedReliable = submitSignedReliable
|
||||
public submitAndWait = submitAndWait
|
||||
|
||||
/**
|
||||
* @deprecated Use autofill instead, provided for users familiar with v1
|
||||
|
||||
@@ -15,55 +15,38 @@ async function sleep(ms: number): Promise<void> {
|
||||
})
|
||||
}
|
||||
|
||||
interface SubmitOptions {
|
||||
// If true, autofill a transaction.
|
||||
autofill?: boolean
|
||||
// If true, and the transaction fails locally, do not retry or relay the transaction to other servers.
|
||||
failHard?: boolean
|
||||
// A wallet to sign a transaction. It must be provided when submitting an unsigned transaction.
|
||||
wallet?: Wallet
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits an unsigned transaction.
|
||||
* Submits a signed/unsigned transaction.
|
||||
* Steps performed on a transaction:
|
||||
* 1. Autofill.
|
||||
* 2. Sign & Encode.
|
||||
* 3. Submit.
|
||||
*
|
||||
* @param this - A Client.
|
||||
* @param wallet - A Wallet to sign a transaction.
|
||||
* @param transaction - A transaction to autofill, sign & encode, and submit.
|
||||
* @param opts - (Optional) Options used to sign and submit a transaction.
|
||||
* @param opts.autofill - If true, autofill a transaction.
|
||||
* @param opts.failHard - If true, and the transaction fails locally, do not retry or relay the transaction to other servers.
|
||||
* @param opts.wallet - A wallet to sign a transaction. It must be provided when submitting an unsigned transaction.
|
||||
* @returns A promise that contains SubmitResponse.
|
||||
* @throws RippledError if submit request fails.
|
||||
*/
|
||||
async function submit(
|
||||
this: Client,
|
||||
wallet: Wallet,
|
||||
transaction: Transaction,
|
||||
transaction: Transaction | string,
|
||||
opts?: SubmitOptions,
|
||||
): Promise<SubmitResponse> {
|
||||
const tx = await this.autofill(transaction)
|
||||
const { tx_blob } = wallet.sign(tx)
|
||||
return this.submitSigned(tx_blob)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes and submits a signed transaction.
|
||||
*
|
||||
* @param this - A Client.
|
||||
* @param signedTransaction - A signed transaction to encode (if not already) and submit.
|
||||
* @returns A promise that contains SubmitResponse.
|
||||
* @throws ValidationError if the transaction isn't signed, RippledError if submit request fails.
|
||||
*/
|
||||
async function submitSigned(
|
||||
this: Client,
|
||||
signedTransaction: Transaction | string,
|
||||
): Promise<SubmitResponse> {
|
||||
if (!isSigned(signedTransaction)) {
|
||||
throw new ValidationError('Transaction must be signed')
|
||||
}
|
||||
|
||||
const signedTxEncoded =
|
||||
typeof signedTransaction === 'string'
|
||||
? signedTransaction
|
||||
: encode(signedTransaction)
|
||||
const request: SubmitRequest = {
|
||||
command: 'submit',
|
||||
tx_blob: signedTxEncoded,
|
||||
fail_hard: isAccountDelete(signedTransaction),
|
||||
}
|
||||
return this.request(request)
|
||||
const signedTx = await getSignedTx(this, transaction, opts)
|
||||
return submitRequest(this, signedTx, opts?.failHard)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,62 +55,56 @@ async function submitSigned(
|
||||
* See [Reliable Transaction Submission](https://xrpl.org/reliable-transaction-submission.html).
|
||||
*
|
||||
* @param this - A Client.
|
||||
* @param wallet - A Wallet to sign a transaction.
|
||||
* @param transaction - A transaction to autofill, sign & encode, and submit.
|
||||
* @param opts - (Optional) Options used to sign and submit a transaction.
|
||||
* @param opts.autofill - If true, autofill a transaction.
|
||||
* @param opts.failHard - If true, and the transaction fails locally, do not retry or relay the transaction to other servers.
|
||||
* @param opts.wallet - A wallet to sign a transaction. It must be provided when submitting an unsigned transaction.
|
||||
* @returns A promise that contains TxResponse, that will return when the transaction has been validated.
|
||||
*/
|
||||
async function submitReliable(
|
||||
async function submitAndWait(
|
||||
this: Client,
|
||||
wallet: Wallet,
|
||||
transaction: Transaction,
|
||||
transaction: Transaction | string,
|
||||
opts?: SubmitOptions,
|
||||
): Promise<TxResponse> {
|
||||
const tx = await this.autofill(transaction)
|
||||
const { tx_blob } = wallet.sign(tx)
|
||||
return this.submitSignedReliable(tx_blob)
|
||||
}
|
||||
const signedTx = await getSignedTx(this, transaction, opts)
|
||||
|
||||
/**
|
||||
* Asynchronously submits a transaction and verifies that it has been included in a
|
||||
* validated ledger (or has errored/will not be included for some reason).
|
||||
* See [Reliable Transaction Submission](https://xrpl.org/reliable-transaction-submission.html).
|
||||
*
|
||||
* @param this - A Client.
|
||||
* @param signedTransaction - A signed transaction to encode (if not already) and submit.
|
||||
* @returns A promise that contains TxResponse, that will return when the transaction has been validated.
|
||||
* @throws ValidationError if the request is not signed/doesn't have a LastLedgerSequence, RippledError if the submit request
|
||||
* fails, XrplError if the reliable submission fails.
|
||||
*/
|
||||
async function submitSignedReliable(
|
||||
this: Client,
|
||||
signedTransaction: Transaction | string,
|
||||
): Promise<TxResponse> {
|
||||
if (!isSigned(signedTransaction)) {
|
||||
throw new ValidationError('Transaction must be signed')
|
||||
}
|
||||
if (!hasLastLedgerSequence(signedTransaction)) {
|
||||
if (!hasLastLedgerSequence(signedTx)) {
|
||||
throw new ValidationError(
|
||||
'Transaction must contain a LastLedgerSequence value for reliable submission.',
|
||||
)
|
||||
}
|
||||
|
||||
const signedTxEncoded =
|
||||
typeof signedTransaction === 'string'
|
||||
? signedTransaction
|
||||
: encode(signedTransaction)
|
||||
const txHash = hashes.hashSignedTx(signedTransaction)
|
||||
|
||||
const request: SubmitRequest = {
|
||||
command: 'submit',
|
||||
tx_blob: signedTxEncoded,
|
||||
fail_hard: isAccountDelete(signedTransaction),
|
||||
}
|
||||
await this.request(request)
|
||||
await submitRequest(this, signedTx, opts?.failHard)
|
||||
|
||||
const txHash = hashes.hashSignedTx(signedTx)
|
||||
return waitForFinalTransactionOutcome(this, txHash)
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
// Encodes and submits a signed transaction.
|
||||
async function submitRequest(
|
||||
client: Client,
|
||||
signedTransaction: Transaction | string,
|
||||
failHard = false,
|
||||
): Promise<SubmitResponse> {
|
||||
if (!isSigned(signedTransaction)) {
|
||||
throw new ValidationError('Transaction must be signed')
|
||||
}
|
||||
|
||||
const signedTxEncoded =
|
||||
typeof signedTransaction === 'string'
|
||||
? signedTransaction
|
||||
: encode(signedTransaction)
|
||||
const request: SubmitRequest = {
|
||||
command: 'submit',
|
||||
tx_blob: signedTxEncoded,
|
||||
fail_hard: isAccountDelete(signedTransaction) || failHard,
|
||||
}
|
||||
return client.request(request)
|
||||
}
|
||||
|
||||
/*
|
||||
* The core logic of reliable submission. This polls the ledger until the result of the
|
||||
* transaction can be considered final, meaning it has either been included in a
|
||||
@@ -172,6 +149,35 @@ function isSigned(transaction: Transaction | string): boolean {
|
||||
)
|
||||
}
|
||||
|
||||
// initializes a transaction for a submit request
|
||||
async function getSignedTx(
|
||||
client: Client,
|
||||
transaction: Transaction | string,
|
||||
{ autofill = true, wallet }: SubmitOptions = {},
|
||||
): Promise<Transaction | string> {
|
||||
if (isSigned(transaction)) {
|
||||
return transaction
|
||||
}
|
||||
|
||||
if (!wallet) {
|
||||
throw new ValidationError(
|
||||
'Wallet must be provided when submitting an unsigned transaction',
|
||||
)
|
||||
}
|
||||
|
||||
let tx =
|
||||
typeof transaction === 'string'
|
||||
? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- converts JsonObject to correct Transaction type
|
||||
(decode(transaction) as unknown as Transaction)
|
||||
: transaction
|
||||
|
||||
if (autofill) {
|
||||
tx = await client.autofill(tx)
|
||||
}
|
||||
|
||||
return wallet.sign(tx).tx_blob
|
||||
}
|
||||
|
||||
// checks if there is a LastLedgerSequence as a part of the transaction
|
||||
function hasLastLedgerSequence(transaction: Transaction | string): boolean {
|
||||
const tx = typeof transaction === 'string' ? decode(transaction) : transaction
|
||||
@@ -184,4 +190,4 @@ function isAccountDelete(transaction: Transaction | string): boolean {
|
||||
return tx.TransactionType === 'AccountDelete'
|
||||
}
|
||||
|
||||
export { submit, submitSigned, submitReliable, submitSignedReliable }
|
||||
export { submit, submitAndWait }
|
||||
|
||||
109
test/client/submit.ts
Normal file
109
test/client/submit.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { assert } from 'chai'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { ValidationError } from 'xrpl-local'
|
||||
import { Transaction } from 'xrpl-local/models/transactions'
|
||||
import Wallet from 'xrpl-local/wallet'
|
||||
|
||||
import rippled from '../fixtures/rippled'
|
||||
import { setupClient, teardownClient } from '../setupClient'
|
||||
import { assertRejects } from '../testUtils'
|
||||
|
||||
describe('client.submit', function () {
|
||||
beforeEach(setupClient)
|
||||
afterEach(teardownClient)
|
||||
|
||||
describe('submit unsigned transactions', function () {
|
||||
const publicKey =
|
||||
'030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D'
|
||||
const privateKey =
|
||||
'00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F'
|
||||
const address = 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc'
|
||||
const transaction: Transaction = {
|
||||
TransactionType: 'Payment',
|
||||
Account: address,
|
||||
Destination: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
|
||||
Amount: '20000000',
|
||||
Sequence: 1,
|
||||
Fee: '12',
|
||||
LastLedgerSequence: 12312,
|
||||
}
|
||||
|
||||
it('should submit an unsigned transaction', async function () {
|
||||
const tx = _.cloneDeep(transaction)
|
||||
|
||||
const wallet = new Wallet(publicKey, privateKey)
|
||||
|
||||
this.mockRippled.addResponse('account_info', rippled.account_info.normal)
|
||||
this.mockRippled.addResponse('ledger', rippled.ledger.normal)
|
||||
this.mockRippled.addResponse('server_info', rippled.server_info.normal)
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
try {
|
||||
const response = await this.client.submit(tx, { wallet })
|
||||
assert(response.result.engine_result, 'tesSUCCESS')
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- error type thrown can be any
|
||||
assert(false, `Did not expect an error to be thrown: ${error}`)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw a ValidationError when submitting an unsigned transaction without a wallet', async function () {
|
||||
const tx: Transaction = _.cloneDeep(transaction)
|
||||
delete tx.SigningPubKey
|
||||
delete tx.TxnSignature
|
||||
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
await assertRejects(
|
||||
this.client.submit(tx),
|
||||
ValidationError,
|
||||
'Wallet must be provided when submitting an unsigned transaction',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('submit signed transactions', function () {
|
||||
const signedTransaction: Transaction = {
|
||||
TransactionType: 'Payment',
|
||||
Sequence: 1,
|
||||
LastLedgerSequence: 12312,
|
||||
Amount: '20000000',
|
||||
Fee: '12',
|
||||
SigningPubKey:
|
||||
'030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D',
|
||||
TxnSignature:
|
||||
'3045022100B3D311371EDAB371CD8F2B661A04B800B61D4B132E09B7B0712D3B2F11B1758302203906B44C4A150311D74FF6A35B146763C0B5B40AC30BD815113F058AA17B3E63',
|
||||
Account: 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc',
|
||||
Destination: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
|
||||
}
|
||||
|
||||
it('should submit a signed transaction', async function () {
|
||||
const signedTx = { ...signedTransaction }
|
||||
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
try {
|
||||
const response = await this.client.submit(signedTx)
|
||||
assert(response.result.engine_result, 'tesSUCCESS')
|
||||
} catch (_error) {
|
||||
assert(false, 'Did not expect an error to be thrown')
|
||||
}
|
||||
})
|
||||
|
||||
it("should submit a signed transaction that's already encoded", async function () {
|
||||
const signedTxEncoded =
|
||||
'1200002400000001201B00003018614000000001312D0068400000000000000C7321030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D74473045022100B3D311371EDAB371CD8F2B661A04B800B61D4B132E09B7B0712D3B2F11B1758302203906B44C4A150311D74FF6A35B146763C0B5B40AC30BD815113F058AA17B3E6381142AF1861DEC1316AEEC995C94FF9E2165B1B784608314FDB08D07AAA0EB711793A3027304D688E10C3648'
|
||||
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
try {
|
||||
const response = await this.client.submit(signedTxEncoded)
|
||||
assert(response.result.engine_result, 'tesSUCCESS')
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- error type thrown can be any
|
||||
assert(false, `Did not expect an error to be thrown: ${error}`)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,69 +0,0 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { ValidationError } from 'xrpl-local'
|
||||
import { Transaction } from 'xrpl-local/models/transactions'
|
||||
|
||||
import rippled from '../fixtures/rippled'
|
||||
import { setupClient, teardownClient } from '../setupClient'
|
||||
import { assertRejects } from '../testUtils'
|
||||
|
||||
describe('client.submitSigned', function () {
|
||||
beforeEach(setupClient)
|
||||
afterEach(teardownClient)
|
||||
|
||||
const signedTransaction: Transaction = {
|
||||
TransactionType: 'Payment',
|
||||
Sequence: 1,
|
||||
LastLedgerSequence: 12312,
|
||||
Amount: '20000000',
|
||||
Fee: '12',
|
||||
SigningPubKey:
|
||||
'030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D',
|
||||
TxnSignature:
|
||||
'3045022100B3D311371EDAB371CD8F2B661A04B800B61D4B132E09B7B0712D3B2F11B1758302203906B44C4A150311D74FF6A35B146763C0B5B40AC30BD815113F058AA17B3E63',
|
||||
Account: 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc',
|
||||
Destination: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
|
||||
}
|
||||
|
||||
it('should submit a signed transaction', async function () {
|
||||
const signedTx: Transaction = { ...signedTransaction }
|
||||
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
try {
|
||||
const response = await this.client.submitSigned(signedTx)
|
||||
assert(response.result.engine_result, 'tesSUCCESS')
|
||||
} catch (_error) {
|
||||
assert(false, 'Did not expect an error to be thrown')
|
||||
}
|
||||
})
|
||||
|
||||
it("should submit a signed transaction that's already encoded", async function () {
|
||||
const signedTxEncoded =
|
||||
'1200002400000001201B00003018614000000001312D0068400000000000000C7321030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D74473045022100B3D311371EDAB371CD8F2B661A04B800B61D4B132E09B7B0712D3B2F11B1758302203906B44C4A150311D74FF6A35B146763C0B5B40AC30BD815113F058AA17B3E6381142AF1861DEC1316AEEC995C94FF9E2165B1B784608314FDB08D07AAA0EB711793A3027304D688E10C3648'
|
||||
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
try {
|
||||
const response = await this.client.submitSigned(signedTxEncoded)
|
||||
assert(response.result.engine_result, 'tesSUCCESS')
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- error type thrown can be any
|
||||
assert(false, `Did not expect an error to be thrown: ${error}`)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw a ValidationError when submitting an unsigned transaction', async function () {
|
||||
const signedTx: Transaction = { ...signedTransaction }
|
||||
delete signedTx.SigningPubKey
|
||||
delete signedTx.TxnSignature
|
||||
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
await assertRejects(
|
||||
this.client.submitSigned(signedTx),
|
||||
ValidationError,
|
||||
'Transaction must be signed',
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,44 +0,0 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { Transaction } from 'xrpl-local/models/transactions'
|
||||
import Wallet from 'xrpl-local/wallet'
|
||||
|
||||
import rippled from '../fixtures/rippled'
|
||||
import { setupClient, teardownClient } from '../setupClient'
|
||||
|
||||
describe('client.submit', function () {
|
||||
beforeEach(setupClient)
|
||||
afterEach(teardownClient)
|
||||
|
||||
const publicKey =
|
||||
'030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D'
|
||||
const privateKey =
|
||||
'00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F'
|
||||
const address = 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc'
|
||||
|
||||
it('should submit an unsigned transaction', async function () {
|
||||
const tx: Transaction = {
|
||||
TransactionType: 'Payment',
|
||||
Account: address,
|
||||
Destination: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
|
||||
Amount: '20000000',
|
||||
Sequence: 1,
|
||||
Fee: '12',
|
||||
LastLedgerSequence: 12312,
|
||||
}
|
||||
const wallet = new Wallet(publicKey, privateKey)
|
||||
|
||||
this.mockRippled.addResponse('account_info', rippled.account_info.normal)
|
||||
this.mockRippled.addResponse('ledger', rippled.ledger.normal)
|
||||
this.mockRippled.addResponse('server_info', rippled.server_info.normal)
|
||||
this.mockRippled.addResponse('submit', rippled.submit.success)
|
||||
|
||||
try {
|
||||
const response = await this.client.submit(wallet, tx)
|
||||
assert(response.result.engine_result, 'tesSUCCESS')
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- error type thrown can be any
|
||||
assert(false, `Did not expect an error to be thrown: ${error}`)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -66,7 +66,7 @@ describe('integration tests', function () {
|
||||
const { tx_blob: tx_blob1 } = signerWallet1.sign(accountSetTx, true)
|
||||
const { tx_blob: tx_blob2 } = signerWallet2.sign(accountSetTx, true)
|
||||
const multisignedTx = multisign([tx_blob1, tx_blob2])
|
||||
const submitResponse = await client.submitSigned(multisignedTx)
|
||||
const submitResponse = await client.submit(multisignedTx)
|
||||
await ledgerAccept(client)
|
||||
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
|
||||
await verifySubmittedTransaction(this.client, multisignedTx)
|
||||
|
||||
@@ -47,7 +47,7 @@ async function generateFundedWalletWithRegularKey(
|
||||
}
|
||||
|
||||
// Add a regular key to the first account
|
||||
await client.submit(masterWallet, setRegularTx)
|
||||
await client.submit(setRegularTx, { wallet: masterWallet })
|
||||
|
||||
if (disableMasterKey) {
|
||||
const accountSet: AccountSet = {
|
||||
@@ -112,7 +112,7 @@ describe('regular key', function () {
|
||||
}
|
||||
|
||||
const client: Client = this.client
|
||||
const response = await client.submit(masterWallet, tx)
|
||||
const response = await client.submit(tx, { wallet: masterWallet })
|
||||
assert.equal(
|
||||
response.result.engine_result,
|
||||
'tefMASTER_DISABLED',
|
||||
@@ -151,7 +151,9 @@ describe('regular key', function () {
|
||||
}
|
||||
|
||||
const client: Client = this.client
|
||||
const response = await client.submit(masterWallet, enableMasterKey)
|
||||
const response = await client.submit(enableMasterKey, {
|
||||
wallet: masterWallet,
|
||||
})
|
||||
assert.equal(
|
||||
response.result.engine_result,
|
||||
'tefMASTER_DISABLED',
|
||||
@@ -178,7 +180,7 @@ describe('regular key', function () {
|
||||
},
|
||||
}
|
||||
|
||||
const response2 = await client.submit(regularKeyWallet, tx)
|
||||
const response2 = await client.submit(tx, { wallet: regularKeyWallet })
|
||||
assert.equal(
|
||||
response2.result.engine_result,
|
||||
'tefBAD_AUTH',
|
||||
@@ -225,7 +227,7 @@ describe('regular key', function () {
|
||||
const signed1 = regularKeyWallet.sign(accountSetTx, true)
|
||||
const signed2 = signerWallet2.sign(accountSetTx, true)
|
||||
const multisigned = multisign([signed1.tx_blob, signed2.tx_blob])
|
||||
const submitResponse = await client.submitSigned(multisigned)
|
||||
const submitResponse = await client.submit(multisigned)
|
||||
await ledgerAccept(client)
|
||||
|
||||
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
|
||||
@@ -276,7 +278,7 @@ describe('regular key', function () {
|
||||
const signed1 = sameKeyDefaultAddressWallet.sign(accountSetTx, true)
|
||||
const signed2 = signerWallet2.sign(accountSetTx, true)
|
||||
const multisigned = multisign([signed1.tx_blob, signed2.tx_blob])
|
||||
const submitResponse = await client.submitSigned(multisigned)
|
||||
const submitResponse = await client.submit(multisigned)
|
||||
await ledgerAccept(client)
|
||||
assert.strictEqual(submitResponse.result.engine_result, 'tefBAD_SIGNATURE')
|
||||
})
|
||||
|
||||
@@ -118,7 +118,7 @@ describe('subscribe', function () {
|
||||
|
||||
// The transactions_proposed stream should trigger the transaction handler WITHOUT ledgerAccept
|
||||
const client: Client = this.client
|
||||
client.submit(this.wallet, tx)
|
||||
client.submit(tx, { wallet: this.wallet })
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -25,10 +25,9 @@ describe('tx', function () {
|
||||
Domain: convertStringToHex('example.com'),
|
||||
}
|
||||
|
||||
const response: SubmitResponse = await this.client.submit(
|
||||
this.wallet,
|
||||
accountSet,
|
||||
)
|
||||
const response: SubmitResponse = await this.client.submit(accountSet, {
|
||||
wallet: this.wallet,
|
||||
})
|
||||
|
||||
const hash = hashSignedTx(response.result.tx_blob)
|
||||
const txResponse = await this.client.request({
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
import { assert } from 'chai'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { AccountSet, convertStringToHex } from 'xrpl-local'
|
||||
import { AccountSet, convertStringToHex, ValidationError } from 'xrpl-local'
|
||||
|
||||
import { assertRejects } from '../testUtils'
|
||||
|
||||
import serverUrl from './serverUrl'
|
||||
import { setupClient, teardownClient } from './setup'
|
||||
@@ -12,19 +14,21 @@ import { ledgerAccept } from './utils'
|
||||
// how long before each test case times out
|
||||
const TIMEOUT = 60000
|
||||
|
||||
describe('reliable submission', function () {
|
||||
describe('client.submitAndWait', function () {
|
||||
this.timeout(TIMEOUT)
|
||||
|
||||
beforeEach(_.partial(setupClient, serverUrl))
|
||||
afterEach(teardownClient)
|
||||
|
||||
it('submitReliable', async function () {
|
||||
it('submitAndWait an unsigned transaction', async function () {
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: this.wallet.classicAddress,
|
||||
Domain: convertStringToHex('example.com'),
|
||||
}
|
||||
const responsePromise = this.client.submitReliable(this.wallet, accountSet)
|
||||
const responsePromise = this.client.submitAndWait(accountSet, {
|
||||
wallet: this.wallet,
|
||||
})
|
||||
const ledgerPromise = setTimeout(ledgerAccept, 1000, this.client)
|
||||
return Promise.all([responsePromise, ledgerPromise]).then(
|
||||
([response, _ledger]) => {
|
||||
@@ -34,7 +38,21 @@ describe('reliable submission', function () {
|
||||
)
|
||||
})
|
||||
|
||||
it('submitSignedReliable', async function () {
|
||||
it('should throw a ValidationError when submitting an unsigned transaction without a wallet', async function () {
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: this.wallet.classicAddress,
|
||||
Domain: convertStringToHex('example.com'),
|
||||
}
|
||||
|
||||
await assertRejects(
|
||||
this.client.submitAndWait(accountSet),
|
||||
ValidationError,
|
||||
'Wallet must be provided when submitting an unsigned transaction',
|
||||
)
|
||||
})
|
||||
|
||||
it('submitAndWait a signed transaction', async function () {
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: this.wallet.classicAddress,
|
||||
@@ -43,7 +61,7 @@ describe('reliable submission', function () {
|
||||
const { tx_blob: signedAccountSet } = this.wallet.sign(
|
||||
await this.client.autofill(accountSet),
|
||||
)
|
||||
const responsePromise = this.client.submitSignedReliable(signedAccountSet)
|
||||
const responsePromise = this.client.submitAndWait(signedAccountSet)
|
||||
const ledgerPromise = setTimeout(ledgerAccept, 1000, this.client)
|
||||
return Promise.all([responsePromise, ledgerPromise]).then(
|
||||
([response, _ledger]) => {
|
||||
@@ -53,7 +71,7 @@ describe('reliable submission', function () {
|
||||
)
|
||||
})
|
||||
|
||||
it('submitSignedReliable longer', async function () {
|
||||
it('submitAndWait a signed transaction longer', async function () {
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: this.wallet.classicAddress,
|
||||
@@ -62,7 +80,7 @@ describe('reliable submission', function () {
|
||||
const { tx_blob: signedAccountSet } = this.wallet.sign(
|
||||
await this.client.autofill(accountSet),
|
||||
)
|
||||
const responsePromise = this.client.submitSignedReliable(signedAccountSet)
|
||||
const responsePromise = this.client.submitAndWait(signedAccountSet)
|
||||
const ledgerPromise = setTimeout(ledgerAccept, 5000, this.client)
|
||||
return Promise.all([responsePromise, ledgerPromise]).then(
|
||||
([response, _ledger]) => {
|
||||
@@ -28,8 +28,8 @@ describe('PaymentChannelClaim', function () {
|
||||
}
|
||||
|
||||
const paymentChannelResponse = await this.client.submit(
|
||||
this.wallet,
|
||||
paymentChannelCreate,
|
||||
{ wallet: this.wallet },
|
||||
)
|
||||
|
||||
await testTransaction(this.client, paymentChannelCreate, this.wallet)
|
||||
|
||||
@@ -28,8 +28,8 @@ describe('PaymentChannelFund', function () {
|
||||
}
|
||||
|
||||
const paymentChannelResponse = await this.client.submit(
|
||||
this.wallet,
|
||||
paymentChannelCreate,
|
||||
{ wallet: this.wallet },
|
||||
)
|
||||
await testTransaction(this.client, paymentChannelCreate, this.wallet)
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@ export async function fundAccount(
|
||||
// 2 times the amount needed for a new account (20 XRP)
|
||||
Amount: '400000000',
|
||||
}
|
||||
const response = await client.submit(Wallet.fromSeed(masterSecret), payment)
|
||||
const response = await client.submit(payment, {
|
||||
wallet: Wallet.fromSeed(masterSecret),
|
||||
})
|
||||
if (response.result.engine_result !== 'tesSUCCESS') {
|
||||
// eslint-disable-next-line no-console -- happens only when something goes wrong
|
||||
console.log(response)
|
||||
@@ -86,7 +88,7 @@ export async function testTransaction(
|
||||
await ledgerAccept(client)
|
||||
|
||||
// sign/submit the transaction
|
||||
const response = await client.submit(wallet, transaction)
|
||||
const response = await client.submit(transaction, { wallet })
|
||||
|
||||
// check that the transaction was successful
|
||||
assert.equal(response.type, 'response')
|
||||
|
||||
Reference in New Issue
Block a user