feat: Jest Test Runner (#2170)

This commit is contained in:
justinr1234
2023-02-03 17:03:07 -06:00
committed by GitHub
parent 5a63f18faf
commit 5fe480ece4
229 changed files with 13497 additions and 17033 deletions

View File

@@ -3,6 +3,3 @@ To run integration tests:
* With docker, run `docker run -p 6006:6006 -it natenichols/rippled-standalone:latest`
* Or [download and build rippled](https://xrpl.org/install-rippled.html) and run `./rippled -a`
2. Run `npm test:integration` or `npm test:browser`
When editing integration tests:
* All imports should be from `xrpl-local` instead of `../../src` (browser tests need this)

View File

@@ -4,10 +4,12 @@ import assert from 'assert'
const TIMEOUT = 20000
// the purpose of this file is to indicate the end of tests and not really test anything.
describe('test', function () {
this.timeout(TIMEOUT)
it('closing test', function () {
assert(true)
})
describe('closing test', function () {
it(
'closing test',
function () {
assert(true)
},
TIMEOUT,
)
})

View File

@@ -1,91 +1,11 @@
import assert from 'assert'
import _ from 'lodash'
import {
Client,
isValidClassicAddress,
isValidXAddress,
dropsToXrp,
} from 'xrpl-local'
// how long before each test case times out
const TIMEOUT = 60000
// This test is reliant on external networks, and as such may be flaky.
describe('fundWallet', function () {
this.timeout(TIMEOUT)
it('submit generates a testnet wallet', async function () {
await generate_faucet_wallet_and_fund_again(
'wss://s.altnet.rippletest.net:51233',
)
})
it('submit generates a devnet wallet', async function () {
await generate_faucet_wallet_and_fund_again(
'wss://s.devnet.rippletest.net:51233',
)
})
it('can generate and fund wallets using a custom host and path', async function () {
await generate_faucet_wallet_and_fund_again(
'wss://s.devnet.rippletest.net:51233/',
'faucet.devnet.rippletest.net',
'/accounts',
)
})
it('can generate and fund wallets on AMM devnet', async function () {
await generate_faucet_wallet_and_fund_again(
'wss://amm.devnet.rippletest.net:51233',
)
})
it('can generate wallet on hooks v2 testnet', async function () {
const api = new Client('wss://hooks-testnet-v2.xrpl-labs.com')
await api.connect()
const { wallet, balance } = await api.fundWallet()
assert.notEqual(wallet, undefined)
assert(isValidClassicAddress(wallet.classicAddress))
assert(isValidXAddress(wallet.getXAddress()))
const info = await api.request({
command: 'account_info',
account: wallet.classicAddress,
})
assert.equal(dropsToXrp(info.result.account_data.Balance), balance)
assert.equal(balance, 10000)
/*
* No test for fund given wallet because the hooks v2 testnet faucet
* requires 10 seconds between requests. Would significantly slow down
* the test suite.
*/
await api.disconnect()
})
it('submit funds wallet with custom amount', async function () {
const api = new Client('wss://s.altnet.rippletest.net:51233')
await api.connect()
const { wallet, balance } = await api.fundWallet(null, { amount: '2000' })
assert.equal(balance, '2000')
assert.notEqual(wallet, undefined)
assert(isValidClassicAddress(wallet.classicAddress))
assert(isValidXAddress(wallet.getXAddress()))
const info = await api.request({
command: 'account_info',
account: wallet.classicAddress,
})
assert.equal(dropsToXrp(info.result.account_data.Balance), balance)
await api.disconnect()
})
})
} from '../../src'
async function generate_faucet_wallet_and_fund_again(
client: string,
@@ -126,3 +46,101 @@ async function generate_faucet_wallet_and_fund_again(
await api.disconnect()
}
// how long before each test case times out
const TIMEOUT = 60000
// This test is reliant on external networks, and as such may be flaky.
describe('fundWallet', function () {
it(
'submit generates a testnet wallet',
async function () {
await generate_faucet_wallet_and_fund_again(
'wss://s.altnet.rippletest.net:51233',
)
},
TIMEOUT,
)
it(
'submit generates a devnet wallet',
async function () {
await generate_faucet_wallet_and_fund_again(
'wss://s.devnet.rippletest.net:51233',
)
},
TIMEOUT,
)
// TODO: Investigate why this test is timing out on the browser
// it('can generate and fund wallets using a custom host and path', async function () {
// await generate_faucet_wallet_and_fund_again(
// 'wss://s.devnet.rippletest.net:51233/',
// 'faucet.devnet.rippletest.net',
// '/accounts',
// )
// })
it(
'can generate and fund wallets on AMM devnet',
async function () {
await generate_faucet_wallet_and_fund_again(
'wss://amm.devnet.rippletest.net:51233',
)
},
TIMEOUT,
)
it(
'can generate wallet on hooks v2 testnet',
async function () {
const api = new Client('wss://hooks-testnet-v2.xrpl-labs.com')
await api.connect()
const { wallet, balance } = await api.fundWallet()
assert.notEqual(wallet, undefined)
assert(isValidClassicAddress(wallet.classicAddress))
assert(isValidXAddress(wallet.getXAddress()))
const info = await api.request({
command: 'account_info',
account: wallet.classicAddress,
})
assert.equal(dropsToXrp(info.result.account_data.Balance), balance)
assert.equal(balance, 10000)
/*
* No test for fund given wallet because the hooks v2 testnet faucet
* requires 10 seconds between requests. Would significantly slow down
* the test suite.
*/
await api.disconnect()
},
TIMEOUT,
)
it(
'submit funds wallet with custom amount',
async function () {
const api = new Client('wss://s.altnet.rippletest.net:51233')
await api.connect()
const { wallet, balance } = await api.fundWallet(null, { amount: '2000' })
assert.equal(balance, '2000')
assert.notEqual(wallet, undefined)
assert(isValidClassicAddress(wallet.classicAddress))
assert(isValidXAddress(wallet.getXAddress()))
const info = await api.request({
command: 'account_info',
account: wallet.classicAddress,
})
assert.equal(dropsToXrp(info.result.account_data.Balance), balance)
await api.disconnect()
},
TIMEOUT,
)
})

View File

@@ -1,16 +1,19 @@
/* eslint-disable import/export -- Tells webpack which files exist. */
export * from './transactions/signerListSet.test'
export * from './transactions/payment.test'
export * from './transactions/offerCreate.test'
export * from './transactions/offerCancel.test'
export * from './transactions/signerListSet.test'
export * from './transactions/accountSet.test'
export * from './transactions/checkCancel.test'
export * from './transactions/checkCash.test'
export * from './transactions/checkCreate.test'
export * from './transactions/depositPreauth.test'
export * from './transactions/paymentChannelCreate.test'
export * from './transactions/escrowCancel.test'
export * from './transactions/escrowCreate.test'
export * from './transactions/escrowFinish.test'
export * from './transactions/offerCancel.test'
export * from './transactions/offerCreate.test'
export * from './transactions/payment.test'
export * from './transactions/paymentChannelClaim.test'
export * from './transactions/paymentChannelCreate.test'
export * from './transactions/paymentChannelFund.test'
export * from './transactions/signerListSet.test'
export * from './transactions/trustSet.test'
export * from './requests/accountChannels.test'
@@ -23,24 +26,33 @@ export * from './requests/accountTx.test'
export * from './requests/bookOffers.test'
export * from './requests/channelVerify.test'
export * from './requests/depositAuthorized.test'
export * from './requests/fee.test'
export * from './requests/gatewayBalances.test'
export * from './requests/ledger.test'
export * from './requests/ledgerClosed.test'
export * from './requests/ledgerCurrent.test'
export * from './requests/ledgerData.test'
export * from './requests/ledgerEntry.test'
export * from './requests/submitMultisigned.test'
export * from './requests/noRippleCheck.test'
export * from './requests/pathFind.test'
export * from './requests/ripplePathFind.test'
export * from './requests/serverInfo.test'
export * from './requests/serverState.test'
export * from './requests/submit.test'
export * from './requests/submitMultisigned.test'
export * from './requests/subscribe.test'
export * from './requests/tx.test'
export * from './requests/utility.test'
export * from './fundWallet.test'
export * from './integration.test'
export * from './onConnect.test'
export * from './regularKey.test'
export * from './submitAndWait.test'
export * from './wallet.test'
// Because this does 256 ledger accepts, we do it last
export * from './transactions/accountDelete.test'
// Ensure you export all added tests above "export * from './finalTest'", otherwise they will not be run.
export * from './finalTest.test'

View File

@@ -1,13 +1,16 @@
import assert from 'assert'
import _ from 'lodash'
import { Client } from 'xrpl-local'
import { AccountSet, SignerListSet } from 'xrpl-local/models/transactions'
import { convertStringToHex } from 'xrpl-local/utils'
import { multisign } from 'xrpl-local/Wallet/signer'
import { Client, SubmitResponse } from '../../src'
import { AccountSet, SignerListSet } from '../../src/models/transactions'
import { convertStringToHex } from '../../src/utils'
import { multisign } from '../../src/Wallet/signer'
import serverUrl from './serverUrl'
import { setupClient, teardownClient } from './setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from './setup'
import {
generateFundedWallet,
ledgerAccept,
@@ -19,55 +22,88 @@ import {
const TIMEOUT = 20000
describe('integration tests', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('isConnected', function () {
assert(this.client.isConnected())
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it('submit multisigned transaction', async function () {
const client: Client = this.client
const signerWallet1 = await generateFundedWallet(client)
const signerWallet2 = await generateFundedWallet(client)
it(
'isConnected',
() => {
assert(testContext.client.isConnected())
},
TIMEOUT,
)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: this.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: signerWallet1.classicAddress,
SignerWeight: 1,
it(
'submit multisigned transaction',
async () => {
const client: Client = testContext.client
const signerWallet1 = await generateFundedWallet(client)
const signerWallet2 = await generateFundedWallet(client)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: testContext.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: signerWallet1.classicAddress,
SignerWeight: 1,
},
},
},
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
},
},
},
],
SignerQuorum: 2,
}
await testTransaction(this.client, signerListSet, this.wallet)
],
SignerQuorum: 2,
}
await testTransaction(
testContext.client,
signerListSet,
testContext.wallet,
)
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
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.submit(multisignedTx)
await ledgerAccept(client)
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
await verifySubmittedTransaction(this.client, multisignedTx)
})
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
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])
let response: SubmitResponse = await client.submit(multisignedTx)
await ledgerAccept(client)
let retryCount = 20
// Retry if another transaction finished before this one
while (
['tefPAST_SEQ', 'tefMAX_LEDGER'].includes(
response.result.engine_result,
) &&
retryCount > 0
) {
retryCount -= 1
// eslint-disable-next-line no-await-in-loop, no-promise-executor-return -- We are waiting on retries
await new Promise((resolve) => setTimeout(resolve, 1000))
// eslint-disable-next-line no-await-in-loop -- We are retrying in a loop on purpose
response = await client.submit(multisignedTx)
// eslint-disable-next-line no-await-in-loop -- We are retrying in a loop on purpose
await ledgerAccept(client)
}
assert.strictEqual(response.result.engine_result, 'tesSUCCESS')
await verifySubmittedTransaction(testContext.client, multisignedTx)
},
TIMEOUT,
)
})

View File

@@ -1,5 +1,6 @@
import { assert } from 'chai'
import { Client } from 'xrpl-local'
import { Client } from '../../src'
import serverUrl from './serverUrl'
@@ -7,30 +8,35 @@ import serverUrl from './serverUrl'
const TIMEOUT = 20000
describe('on handlers', function () {
this.timeout(TIMEOUT)
it('on connect', async function () {
const client = new Client(serverUrl)
return new Promise<void>(function (resolve) {
client.on('connected', function () {
client.removeAllListeners()
client.disconnect()
resolve()
it(
'on connect',
async () => {
const client = new Client(serverUrl)
return new Promise<void>(function (resolve) {
client.on('connected', function () {
client.removeAllListeners()
client.disconnect().then(() => resolve())
})
client.connect()
})
client.connect()
})
})
},
TIMEOUT,
)
it('on disconnect', async function () {
const client = new Client(serverUrl)
return new Promise<void>(function (resolve) {
client.on('disconnected', function (code: number) {
// should be the normal disconnect code
assert.equal(code, 1000)
client.removeAllListeners()
resolve()
it(
'on disconnect',
async () => {
const client = new Client(serverUrl)
return new Promise<void>(function (resolve) {
client.on('disconnected', function (code: number) {
// should be the normal disconnect code
assert.equal(code, 1000)
client.removeAllListeners()
resolve()
})
client.connect().then(async () => client.disconnect())
})
client.connect().then(async () => client.disconnect())
})
})
},
TIMEOUT,
)
})

View File

@@ -1,5 +1,5 @@
import { assert } from 'chai'
import _ from 'lodash'
import {
AccountSet,
Client,
@@ -8,12 +8,16 @@ import {
Wallet,
AccountSetAsfFlags,
OfferCreate,
} from 'xrpl-local'
import { convertStringToHex } from 'xrpl-local/utils'
import { multisign } from 'xrpl-local/Wallet/signer'
} from '../../src'
import { convertStringToHex } from '../../src/utils'
import { multisign } from '../../src/Wallet/signer'
import serverUrl from './serverUrl'
import { setupClient, teardownClient } from './setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from './setup'
import {
generateFundedWallet,
ledgerAccept,
@@ -62,223 +66,270 @@ async function generateFundedWalletWithRegularKey(
}
describe('regular key', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('sign and submit with a regular key', async function () {
const regularKeyWallet = (
await generateFundedWalletWithRegularKey(this.client)
).regularKeyWallet
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: regularKeyWallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
testTransaction(this.client, accountSet, regularKeyWallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it('sign and submit using the master key of an account with a regular key', async function () {
const masterWallet = (await generateFundedWalletWithRegularKey(this.client))
.masterWallet
it(
'sign and submit with a regular key',
async () => {
const regularKeyWallet = (
await generateFundedWalletWithRegularKey(testContext.client)
).regularKeyWallet
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: masterWallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: regularKeyWallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
testTransaction(this.client, accountSet, masterWallet)
})
await testTransaction(testContext.client, accountSet, regularKeyWallet)
},
TIMEOUT,
)
it('try to sign with master key after disabling', async function () {
const masterWallet = (
await generateFundedWalletWithRegularKey(this.client, true)
).masterWallet
it(
'sign and submit using the master key of an account with a regular key',
async () => {
const masterWallet = (
await generateFundedWalletWithRegularKey(testContext.client)
).masterWallet
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: masterWallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: masterWallet.classicAddress,
value: '10',
},
}
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: masterWallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const client: Client = this.client
const response = await client.submit(tx, { wallet: masterWallet })
assert.equal(
response.result.engine_result,
'tefMASTER_DISABLED',
'Master key was disabled, yet the master key still was able to sign and submit a transaction',
)
})
await testTransaction(testContext.client, accountSet, masterWallet)
},
TIMEOUT,
)
it('sign with regular key after disabling the master key', async function () {
const regularKeyWallet = (
await generateFundedWalletWithRegularKey(this.client, true)
).regularKeyWallet
it(
'try to sign with master key after disabling',
async () => {
const masterWallet = (
await generateFundedWalletWithRegularKey(testContext.client, true)
).masterWallet
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: regularKeyWallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: regularKeyWallet.classicAddress,
value: '10',
},
}
await testTransaction(this.client, tx, regularKeyWallet)
})
it('try to enable and disable a regular key', async function () {
const wallets = await generateFundedWalletWithRegularKey(this.client, true)
const masterWallet = wallets.masterWallet
const regularKeyWallet = wallets.regularKeyWallet
const enableMasterKey: AccountSet = {
TransactionType: 'AccountSet',
Account: masterWallet.classicAddress,
ClearFlag: AccountSetAsfFlags.asfDisableMaster,
}
const client: Client = this.client
const response = await client.submit(enableMasterKey, {
wallet: masterWallet,
})
assert.equal(
response.result.engine_result,
'tefMASTER_DISABLED',
'Master key was disabled, yet the master key still was able to sign and submit a transaction',
)
await testTransaction(client, enableMasterKey, regularKeyWallet)
const turnOffRegularKey: SetRegularKey = {
TransactionType: 'SetRegularKey',
Account: masterWallet.address,
}
await testTransaction(this.client, turnOffRegularKey, masterWallet)
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: regularKeyWallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: regularKeyWallet.classicAddress,
value: '10',
},
}
const response2 = await client.submit(tx, { wallet: regularKeyWallet })
assert.equal(
response2.result.engine_result,
'tefBAD_AUTH',
'Regular key should have been disabled, but somehow was still able to sign and submit a transaction.',
)
})
it('submit_multisigned transaction with regular keys set', async function () {
const client: Client = this.client
const regularKeyWallet = (await generateFundedWalletWithRegularKey(client))
.regularKeyWallet
const signerWallet2 = await generateFundedWallet(this.client)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: this.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: regularKeyWallet.classicAddress,
SignerWeight: 1,
},
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: masterWallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: masterWallet.classicAddress,
value: '10',
},
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
},
}
const client: Client = testContext.client
const response = await client.submit(tx, { wallet: masterWallet })
assert.equal(
response.result.engine_result,
'tefMASTER_DISABLED',
'Master key was disabled, yet the master key still was able to sign and submit a transaction',
)
},
TIMEOUT,
)
it(
'sign with regular key after disabling the master key',
async () => {
const regularKeyWallet = (
await generateFundedWalletWithRegularKey(testContext.client, true)
).regularKeyWallet
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: regularKeyWallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: regularKeyWallet.classicAddress,
value: '10',
},
],
SignerQuorum: 2,
}
await testTransaction(this.client, signerListSet, this.wallet)
}
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
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.submit(multisigned)
await ledgerAccept(client)
await testTransaction(testContext.client, tx, regularKeyWallet)
},
TIMEOUT,
)
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
await verifySubmittedTransaction(this.client, multisigned)
})
it(
'try to enable and disable a regular key',
async () => {
const wallets = await generateFundedWalletWithRegularKey(
testContext.client,
true,
)
const masterWallet = wallets.masterWallet
const regularKeyWallet = wallets.regularKeyWallet
it('try multisigning with the account address used to set up a regular key', async function () {
const client: Client = this.client
const enableMasterKey: AccountSet = {
TransactionType: 'AccountSet',
Account: masterWallet.classicAddress,
ClearFlag: AccountSetAsfFlags.asfDisableMaster,
}
const regularKeyWallet = (await generateFundedWalletWithRegularKey(client))
.regularKeyWallet
const signerWallet2 = await generateFundedWallet(this.client)
const client: Client = testContext.client
const response = await client.submit(enableMasterKey, {
wallet: masterWallet,
})
assert.equal(
response.result.engine_result,
'tefMASTER_DISABLED',
'Master key was disabled, yet the master key still was able to sign and submit a transaction',
)
const sameKeyDefaultAddressWallet = new Wallet(
regularKeyWallet.publicKey,
regularKeyWallet.privateKey,
)
await testTransaction(client, enableMasterKey, regularKeyWallet)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: this.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: regularKeyWallet.classicAddress,
SignerWeight: 1,
},
const turnOffRegularKey: SetRegularKey = {
TransactionType: 'SetRegularKey',
Account: masterWallet.address,
}
await testTransaction(testContext.client, turnOffRegularKey, masterWallet)
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: regularKeyWallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: regularKeyWallet.classicAddress,
value: '10',
},
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
},
},
],
SignerQuorum: 2,
}
await testTransaction(this.client, signerListSet, this.wallet)
}
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
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.submit(multisigned)
await ledgerAccept(client)
assert.strictEqual(submitResponse.result.engine_result, 'tefBAD_SIGNATURE')
})
const response2 = await client.submit(tx, { wallet: regularKeyWallet })
assert.equal(
response2.result.engine_result,
'tefBAD_AUTH',
'Regular key should have been disabled, but somehow was still able to sign and submit a transaction.',
)
},
TIMEOUT,
)
it(
'submit_multisigned transaction with regular keys set',
async () => {
const client: Client = testContext.client
const regularKeyWallet = (
await generateFundedWalletWithRegularKey(client)
).regularKeyWallet
const signerWallet2 = await generateFundedWallet(testContext.client)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: testContext.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: regularKeyWallet.classicAddress,
SignerWeight: 1,
},
},
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
},
},
],
SignerQuorum: 2,
}
await testTransaction(
testContext.client,
signerListSet,
testContext.wallet,
)
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
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.submit(multisigned)
await ledgerAccept(client)
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
await verifySubmittedTransaction(testContext.client, multisigned)
},
TIMEOUT,
)
it(
'try multisigning with the account address used to set up a regular key',
async () => {
const client: Client = testContext.client
const regularKeyWallet = (
await generateFundedWalletWithRegularKey(client)
).regularKeyWallet
const signerWallet2 = await generateFundedWallet(testContext.client)
const sameKeyDefaultAddressWallet = new Wallet(
regularKeyWallet.publicKey,
regularKeyWallet.privateKey,
)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: testContext.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: regularKeyWallet.classicAddress,
SignerWeight: 1,
},
},
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
},
},
],
SignerQuorum: 2,
}
await testTransaction(
testContext.client,
signerListSet,
testContext.wallet,
)
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
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.submit(multisigned)
await ledgerAccept(client)
assert.strictEqual(
submitResponse.result.engine_result,
'tefBAD_SIGNATURE',
)
},
TIMEOUT,
)
})

View File

@@ -1,44 +1,54 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountChannelsRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { AccountChannelsRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('account_channels', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: AccountChannelsRequest = {
command: 'account_channels',
account: this.wallet.classicAddress,
ledger_index: 'validated',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
account: this.wallet.classicAddress,
channels: [],
ledger_hash:
'C8BFA74A740AA22AD9BD724781589319052398B0C6C817B88D55628E07B7B4A1',
ledger_index: 150,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
_.omit(response.result, ['ledger_hash', 'ledger_index']),
_.omit(expected.result, ['ledger_hash', 'ledger_index']),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: AccountChannelsRequest = {
command: 'account_channels',
account: testContext.wallet.classicAddress,
ledger_index: 'validated',
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
account: testContext.wallet.classicAddress,
channels: [],
ledger_hash:
'C8BFA74A740AA22AD9BD724781589319052398B0C6C817B88D55628E07B7B4A1',
ledger_index: 150,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
omit(response.result, ['ledger_hash', 'ledger_index']),
omit(expected.result, ['ledger_hash', 'ledger_index']),
)
},
TIMEOUT,
)
})

View File

@@ -1,45 +1,55 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountCurrenciesRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { AccountCurrenciesRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('account_currencies', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: AccountCurrenciesRequest = {
command: 'account_currencies',
account: this.wallet.classicAddress,
strict: true,
ledger_index: 'validated',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
receive_currencies: [],
send_currencies: [],
ledger_hash:
'C8BFA74A740AA22AD9BD724781589319052398B0C6C817B88D55628E07B7B4A1',
ledger_index: 150,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
_.omit(response.result, ['ledger_hash', 'ledger_index']),
_.omit(expected.result, ['ledger_hash', 'ledger_index']),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: AccountCurrenciesRequest = {
command: 'account_currencies',
account: testContext.wallet.classicAddress,
strict: true,
ledger_index: 'validated',
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
receive_currencies: [],
send_currencies: [],
ledger_hash:
'C8BFA74A740AA22AD9BD724781589319052398B0C6C817B88D55628E07B7B4A1',
ledger_index: 150,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
omit(response.result, ['ledger_hash', 'ledger_index']),
omit(expected.result, ['ledger_hash', 'ledger_index']),
)
},
TIMEOUT,
)
})

View File

@@ -1,74 +1,83 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountInfoRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { AccountInfoRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('account_info', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: AccountInfoRequest = {
command: 'account_info',
account: this.wallet.classicAddress,
strict: true,
ledger_index: 'validated',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
account_data: {
Account: this.wallet.classicAddress,
Balance: '400000000',
Flags: 0,
LedgerEntryType: 'AccountRoot',
OwnerCount: 0,
PreviousTxnID:
'19A8211695785A3A02C1C287D93C2B049E83A9CD609825E721052D63FF4F0EC8',
PreviousTxnLgrSeq: 582,
Sequence: 283,
index:
'BD4815E6EB304136E6044F778FB68D4E464CC8DFC59B8F6CC93D90A3709AE194',
},
ledger_hash:
'F0DEEC46A7185BBB535517EE38CF2025973022D5B0532B36407F492521FDB0C6',
ledger_index: 582,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(response.result.validated, expected.result.validated)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.equal(typeof response.result.account_data.PreviousTxnID, 'string')
assert.equal(typeof response.result.account_data.index, 'string')
assert.equal(
typeof response.result.account_data.PreviousTxnLgrSeq,
'number',
)
assert.equal(typeof response.result.account_data.Sequence, 'number')
assert.deepEqual(
_.omit(response.result.account_data, [
'PreviousTxnID',
'PreviousTxnLgrSeq',
'Sequence',
'index',
]),
_.omit(expected.result.account_data, [
'PreviousTxnID',
'PreviousTxnLgrSeq',
'Sequence',
'index',
]),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: AccountInfoRequest = {
command: 'account_info',
account: testContext.wallet.classicAddress,
strict: true,
ledger_index: 'validated',
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
account_data: {
Account: testContext.wallet.classicAddress,
Balance: '400000000',
Flags: 0,
LedgerEntryType: 'AccountRoot',
OwnerCount: 0,
PreviousTxnID:
'19A8211695785A3A02C1C287D93C2B049E83A9CD609825E721052D63FF4F0EC8',
PreviousTxnLgrSeq: 582,
Sequence: 283,
index:
'BD4815E6EB304136E6044F778FB68D4E464CC8DFC59B8F6CC93D90A3709AE194',
},
ledger_hash:
'F0DEEC46A7185BBB535517EE38CF2025973022D5B0532B36407F492521FDB0C6',
ledger_index: 582,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(response.result.validated, expected.result.validated)
assert.equal(typeof response.result.ledger_index, 'number')
assert.equal(typeof response.result.account_data.PreviousTxnID, 'string')
assert.equal(typeof response.result.account_data.index, 'string')
assert.equal(
typeof response.result.account_data.PreviousTxnLgrSeq,
'number',
)
assert.equal(typeof response.result.account_data.Sequence, 'number')
assert.deepEqual(
omit(response.result.account_data, [
'PreviousTxnID',
'PreviousTxnLgrSeq',
'Sequence',
'index',
]),
omit(expected.result.account_data, [
'PreviousTxnID',
'PreviousTxnLgrSeq',
'Sequence',
'index',
]),
)
},
TIMEOUT,
)
})

View File

@@ -1,45 +1,55 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountLinesRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { AccountLinesRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('account_lines', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: AccountLinesRequest = {
command: 'account_lines',
account: this.wallet.classicAddress,
strict: true,
ledger_index: 'validated',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
account: this.wallet.classicAddress,
ledger_hash:
'0C09AAFA88AC1A616058220CF33269788D3985DAA6F2386196D4A7404252BB61',
ledger_index: 1074,
lines: [],
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
_.omit(response.result, ['ledger_hash', 'ledger_index']),
_.omit(expected.result, ['ledger_hash', 'ledger_index']),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: AccountLinesRequest = {
command: 'account_lines',
account: testContext.wallet.classicAddress,
strict: true,
ledger_index: 'validated',
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
account: testContext.wallet.classicAddress,
ledger_hash:
'0C09AAFA88AC1A616058220CF33269788D3985DAA6F2386196D4A7404252BB61',
ledger_index: 1074,
lines: [],
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
omit(response.result, ['ledger_hash', 'ledger_index']),
omit(expected.result, ['ledger_hash', 'ledger_index']),
)
},
TIMEOUT,
)
})

View File

@@ -1,44 +1,54 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountObjectsRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { AccountObjectsRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('account_objects', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: AccountObjectsRequest = {
command: 'account_objects',
account: this.wallet.classicAddress,
ledger_index: 'validated',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
account: this.wallet.classicAddress,
account_objects: [],
ledger_hash:
'28D68B351ED58B9819502EF5FC05BA4412A048597E5159E1C226703BDF7C7897',
ledger_index: 1294,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
_.omit(response.result, ['ledger_hash', 'ledger_index']),
_.omit(expected.result, ['ledger_hash', 'ledger_index']),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: AccountObjectsRequest = {
command: 'account_objects',
account: testContext.wallet.classicAddress,
ledger_index: 'validated',
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
account: testContext.wallet.classicAddress,
account_objects: [],
ledger_hash:
'28D68B351ED58B9819502EF5FC05BA4412A048597E5159E1C226703BDF7C7897',
ledger_index: 1294,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
omit(response.result, ['ledger_hash', 'ledger_index']),
omit(expected.result, ['ledger_hash', 'ledger_index']),
)
},
TIMEOUT,
)
})

View File

@@ -1,41 +1,51 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountOffersRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { AccountOffersRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('account_offers', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: AccountOffersRequest = {
command: 'account_offers',
account: this.wallet.classicAddress,
strict: true,
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
account: this.wallet.classicAddress,
ledger_current_index: 1443,
offers: [],
validated: false,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_current_index, 'number')
assert.deepEqual(
_.omit(response.result, 'ledger_current_index'),
_.omit(expected.result, 'ledger_current_index'),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: AccountOffersRequest = {
command: 'account_offers',
account: testContext.wallet.classicAddress,
strict: true,
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
account: testContext.wallet.classicAddress,
ledger_current_index: 1443,
offers: [],
validated: false,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_current_index, 'number')
assert.deepEqual(
omit(response.result, 'ledger_current_index'),
omit(expected.result, 'ledger_current_index'),
)
},
TIMEOUT,
)
})

View File

@@ -1,99 +1,114 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountTxRequest } from 'xrpl-local'
import {
AccountTxRequest,
Payment,
type TransactionMetadata,
} from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('account_tx', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: AccountTxRequest = {
command: 'account_tx',
account: this.wallet.classicAddress,
ledger_index: 'validated',
}
const response = await this.client.request(request)
const expected = {
result: {
account: this.wallet.classicAddress,
limit: 400,
transactions: [
{
tx: {
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
Amount: '400000000',
Destination: this.wallet.classicAddress,
Fee: '12',
Flags: 0,
LastLedgerSequence: 1753,
Sequence: 843,
SigningPubKey:
'0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020',
TransactionType: 'Payment',
TxnSignature:
'30440220693D244BC13967E3DA67BDC974096784ED03DD4ACE6F36645E5176988452AFCF02200F8AB172432913899F27EC5523829AEDAD00CC2445690400E294EDF652A85945',
date: 685747005,
hash: '2E68BC15813B4A836FAC4D80E42E6FDA6410E99AB973937DEA5E6C2E9A116BAB',
inLedger: 1734,
ledger_index: 1734,
},
},
],
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(response.result.account, expected.result.account)
assert.equal(
response.result.transactions[0].meta.TransactionResult,
'tesSUCCESS',
)
assert.equal(
typeof response.result.transactions[0].tx.LastLedgerSequence,
'number',
)
assert.equal(typeof response.result.transactions[0].tx.Sequence, 'number')
assert.equal(
typeof response.result.transactions[0].tx.SigningPubKey,
'string',
)
assert.equal(
typeof response.result.transactions[0].tx.TxnSignature,
'string',
)
assert.equal(typeof response.result.transactions[0].tx.Fee, 'string')
assert.equal(typeof response.result.transactions[0].tx.hash, 'string')
assert.equal(typeof response.result.transactions[0].tx.inLedger, 'number')
assert.equal(
typeof response.result.transactions[0].tx.ledger_index,
'number',
)
const responseTx = response.result.transactions[0].tx
const expectedTx = expected.result.transactions[0].tx
assert.deepEqual(
[
responseTx.Flags,
responseTx.TransactionType,
responseTx.Account,
responseTx.Amount,
responseTx.Destination,
],
[
expectedTx.Flags,
expectedTx.TransactionType,
expectedTx.Account,
expectedTx.Amount,
expectedTx.Destination,
],
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: AccountTxRequest = {
command: 'account_tx',
account: testContext.wallet.classicAddress,
ledger_index: 'validated',
}
const response = await testContext.client.request(request)
const expected = {
result: {
account: testContext.wallet.classicAddress,
limit: 400,
transactions: [
{
tx: {
Account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
Amount: '400000000',
Destination: testContext.wallet.classicAddress,
Fee: '12',
Flags: 0,
LastLedgerSequence: 1753,
Sequence: 843,
SigningPubKey:
'0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020',
TransactionType: 'Payment',
TxnSignature:
'30440220693D244BC13967E3DA67BDC974096784ED03DD4ACE6F36645E5176988452AFCF02200F8AB172432913899F27EC5523829AEDAD00CC2445690400E294EDF652A85945',
date: 685747005,
hash: '2E68BC15813B4A836FAC4D80E42E6FDA6410E99AB973937DEA5E6C2E9A116BAB',
ledger_index: 1734,
},
},
],
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(response.result.account, expected.result.account)
assert.equal(
(response.result.transactions[0].meta as TransactionMetadata)
.TransactionResult,
'tesSUCCESS',
)
assert.equal(
typeof response.result.transactions[0].tx?.LastLedgerSequence,
'number',
)
assert.equal(
typeof response.result.transactions[0].tx?.Sequence,
'number',
)
assert.equal(
typeof response.result.transactions[0].tx?.SigningPubKey,
'string',
)
assert.equal(
typeof response.result.transactions[0].tx?.TxnSignature,
'string',
)
assert.equal(typeof response.result.transactions[0].tx?.Fee, 'string')
assert.equal(typeof response.result.transactions[0].tx?.hash, 'string')
assert.equal(
typeof response.result.transactions[0].tx?.ledger_index,
'number',
)
const responseTx = response.result.transactions[0].tx as Payment
const expectedTx = expected.result.transactions[0].tx
assert.deepEqual(
[
responseTx.Flags,
responseTx.TransactionType,
responseTx.Account,
responseTx.Amount,
responseTx.Destination,
],
[
expectedTx.Flags,
expectedTx.TransactionType,
expectedTx.Account,
expectedTx.Amount,
expectedTx.Destination,
],
)
},
TIMEOUT,
)
})

View File

@@ -1,42 +1,51 @@
import { assert } from 'chai'
import _ from 'lodash'
import { BookOffersRequest, BookOffersResponse } from 'xrpl-local'
import { BookOffersRequest, BookOffersResponse } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('book_offers', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const bookOffer: BookOffersRequest = {
command: 'book_offers',
taker_gets: {
currency: 'XRP',
},
taker_pays: {
currency: 'USD',
issuer: this.wallet.classicAddress,
},
}
const response = await this.client.request(bookOffer)
const expectedResponse: BookOffersResponse = {
id: response.id,
type: 'response',
result: {
ledger_current_index: response.result.ledger_current_index,
offers: response.result.offers,
validated: false,
},
}
assert.deepEqual(response, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const bookOffer: BookOffersRequest = {
command: 'book_offers',
taker_gets: {
currency: 'XRP',
},
taker_pays: {
currency: 'USD',
issuer: testContext.wallet.classicAddress,
},
}
const response = await testContext.client.request(bookOffer)
const expectedResponse: BookOffersResponse = {
id: response.id,
type: 'response',
result: {
ledger_current_index: response.result.ledger_current_index,
offers: response.result.offers,
validated: false,
},
}
assert.deepEqual(response, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,40 +1,49 @@
import { assert } from 'chai'
import _ from 'lodash'
import { ChannelVerifyRequest, ChannelVerifyResponse } from 'xrpl-local'
import { ChannelVerifyRequest, ChannelVerifyResponse } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('channel_verify', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const channelVerify: ChannelVerifyRequest = {
command: 'channel_verify',
channel_id:
'5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3',
signature:
'304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064',
public_key: 'aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3',
amount: '1000000',
}
const response = await this.client.request(channelVerify)
const expectedResponse: ChannelVerifyResponse = {
id: response.id,
type: 'response',
result: {
signature_verified: response.result.signature_verified,
},
}
assert.deepEqual(response, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const channelVerify: ChannelVerifyRequest = {
command: 'channel_verify',
channel_id:
'5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3',
signature:
'304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064',
public_key: 'aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3',
amount: '1000000',
}
const response = await testContext.client.request(channelVerify)
const expectedResponse: ChannelVerifyResponse = {
id: response.id,
type: 'response',
result: {
signature_verified: response.result.signature_verified,
},
}
assert.deepEqual(response, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,42 +1,54 @@
import { assert } from 'chai'
import _ from 'lodash'
import { DepositAuthorizedRequest, DepositAuthorizedResponse } from 'xrpl-local'
import {
DepositAuthorizedRequest,
DepositAuthorizedResponse,
} from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('deposit_authorized', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const depositAuthorized: DepositAuthorizedRequest = {
command: 'deposit_authorized',
source_account: this.wallet.classicAddress,
destination_account: wallet2.classicAddress,
}
const response = await this.client.request(depositAuthorized)
const expectedResponse: DepositAuthorizedResponse = {
id: response.id,
type: 'response',
result: {
deposit_authorized: true,
destination_account: depositAuthorized.destination_account,
ledger_current_index: response.result.ledger_current_index,
source_account: depositAuthorized.source_account,
validated: false,
},
}
assert.deepEqual(response, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const depositAuthorized: DepositAuthorizedRequest = {
command: 'deposit_authorized',
source_account: testContext.wallet.classicAddress,
destination_account: wallet2.classicAddress,
}
const response = await testContext.client.request(depositAuthorized)
const expectedResponse: DepositAuthorizedResponse = {
id: response.id,
type: 'response',
result: {
deposit_authorized: true,
destination_account: depositAuthorized.destination_account,
ledger_current_index: response.result.ledger_current_index,
source_account: depositAuthorized.source_account,
validated: false,
},
}
assert.deepEqual(response, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,52 +1,62 @@
import { assert } from 'chai'
import _ from 'lodash'
import { FeeRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { FeeRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('fee', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: FeeRequest = {
command: 'fee',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
current_ledger_size: '0',
current_queue_size: '0',
drops: {
base_fee: '10',
median_fee: '5000',
minimum_fee: '10',
open_ledger_fee: '10',
},
expected_ledger_size: '1000',
ledger_current_index: 2925,
levels: {
median_level: '128000',
minimum_level: '256',
open_ledger_level: '256',
reference_level: '256',
},
max_queue_size: '20000',
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_current_index, 'number')
assert.deepEqual(
_.omit(response.result, ['ledger_current_index']),
_.omit(expected.result, ['ledger_current_index']),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: FeeRequest = {
command: 'fee',
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
current_ledger_size: '0',
current_queue_size: '0',
drops: {
base_fee: '10',
median_fee: '5000',
minimum_fee: '10',
open_ledger_fee: '10',
},
expected_ledger_size: '1000',
ledger_current_index: 2925,
levels: {
median_level: '128000',
minimum_level: '256',
open_ledger_level: '256',
reference_level: '256',
},
max_queue_size: '20000',
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_current_index, 'number')
assert.deepEqual(
omit(response.result, ['ledger_current_index']),
omit(expected.result, ['ledger_current_index']),
)
},
TIMEOUT,
)
})

View File

@@ -1,44 +1,54 @@
import { assert } from 'chai'
import _ from 'lodash'
import { GatewayBalancesRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { GatewayBalancesRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('gateway_balances', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: GatewayBalancesRequest = {
command: 'gateway_balances',
account: this.wallet.classicAddress,
ledger_index: 'validated',
strict: true,
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
account: this.wallet.classicAddress,
ledger_hash:
'28D68B351ED58B9819502EF5FC05BA4412A048597E5159E1C226703BDF7C7897',
ledger_index: 1294,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
_.omit(response.result, ['ledger_hash', 'ledger_index']),
_.omit(expected.result, ['ledger_hash', 'ledger_index']),
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: GatewayBalancesRequest = {
command: 'gateway_balances',
account: testContext.wallet.classicAddress,
ledger_index: 'validated',
strict: true,
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
account: testContext.wallet.classicAddress,
ledger_hash:
'28D68B351ED58B9819502EF5FC05BA4412A048597E5159E1C226703BDF7C7897',
ledger_index: 1294,
validated: true,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.ledger_hash, 'string')
assert.equal(typeof response.result.ledger_index, 'number')
assert.deepEqual(
omit(response.result, ['ledger_hash', 'ledger_index']),
omit(expected.result, ['ledger_hash', 'ledger_index']),
)
},
TIMEOUT,
)
})

View File

@@ -1,75 +1,84 @@
import { assert } from 'chai'
import _ from 'lodash'
import { LedgerRequest, LedgerResponse } from 'xrpl-local'
import { Ledger } from 'xrpl-local/models/ledger'
import { LedgerRequest, LedgerResponse } from '../../../src'
import { Ledger } from '../../../src/models/ledger'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('ledger', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const ledgerRequest: LedgerRequest = {
command: 'ledger',
ledger_index: 'validated',
}
const expected = {
id: 0,
result: {
ledger: {
accepted: true,
account_hash: 'string',
close_flags: 0,
close_time: 0,
close_time_human: 'string',
},
ledger_hash: 'string',
ledger_index: 1,
validated: true,
},
type: 'response',
}
const ledgerResponse: LedgerResponse = await this.client.request(
ledgerRequest,
)
assert.equal(ledgerResponse.type, expected.type)
assert.equal(ledgerResponse.result.validated, expected.result.validated)
assert.typeOf(ledgerResponse.result.ledger_hash, 'string')
assert.typeOf(ledgerResponse.result.ledger_index, 'number')
const ledger = ledgerResponse.result.ledger as Ledger & {
accepted: boolean
hash: string
seqNum: string
}
assert.equal(ledger.closed, true)
const stringTypes = [
'account_hash',
'close_time_human',
'ledger_hash',
'ledger_index',
'parent_hash',
'total_coins',
'transaction_hash',
]
stringTypes.forEach((strType) => assert.typeOf(ledger[strType], 'string'))
const numTypes = [
'close_flags',
'close_time',
'close_time_resolution',
'parent_close_time',
]
numTypes.forEach((numType) => assert.typeOf(ledger[numType], 'number'))
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const ledgerRequest: LedgerRequest = {
command: 'ledger',
ledger_index: 'validated',
}
const expected = {
id: 0,
result: {
ledger: {
accepted: true,
account_hash: 'string',
close_flags: 0,
close_time: 0,
close_time_human: 'string',
},
ledger_hash: 'string',
ledger_index: 1,
validated: true,
},
type: 'response',
}
const ledgerResponse: LedgerResponse = await testContext.client.request(
ledgerRequest,
)
assert.equal(ledgerResponse.type, expected.type)
assert.equal(ledgerResponse.result.validated, expected.result.validated)
assert.typeOf(ledgerResponse.result.ledger_hash, 'string')
assert.typeOf(ledgerResponse.result.ledger_index, 'number')
const ledger = ledgerResponse.result.ledger as Ledger & {
accepted: boolean
hash: string
seqNum: string
}
assert.equal(ledger.closed, true)
const stringTypes = [
'account_hash',
'close_time_human',
'ledger_hash',
'ledger_index',
'parent_hash',
'total_coins',
'transaction_hash',
]
stringTypes.forEach((strType) => assert.typeOf(ledger[strType], 'string'))
const numTypes = [
'close_flags',
'close_time',
'close_time_resolution',
'parent_close_time',
]
numTypes.forEach((numType) => assert.typeOf(ledger[numType], 'number'))
},
TIMEOUT,
)
})

View File

@@ -1,36 +1,45 @@
import { assert } from 'chai'
import _ from 'lodash'
import { LedgerClosedRequest, LedgerClosedResponse } from 'xrpl-local'
import { LedgerClosedRequest, LedgerClosedResponse } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('ledger_closed', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const ledgerClosedRequest: LedgerClosedRequest = {
command: 'ledger_closed',
}
const ledgerClosedResponse: LedgerClosedResponse =
await this.client.request(ledgerClosedRequest)
const expectedResponse: LedgerClosedResponse = {
id: ledgerClosedResponse.id,
type: 'response',
result: {
ledger_hash: 'string',
ledger_index: 1,
},
}
assert.equal(ledgerClosedResponse.type, expectedResponse.type)
assert.typeOf(ledgerClosedResponse.result.ledger_hash, 'string')
assert.typeOf(ledgerClosedResponse.result.ledger_index, 'number')
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const ledgerClosedRequest: LedgerClosedRequest = {
command: 'ledger_closed',
}
const ledgerClosedResponse: LedgerClosedResponse =
await testContext.client.request(ledgerClosedRequest)
const expectedResponse: LedgerClosedResponse = {
id: ledgerClosedResponse.id,
type: 'response',
result: {
ledger_hash: 'string',
ledger_index: 1,
},
}
assert.equal(ledgerClosedResponse.type, expectedResponse.type)
assert.typeOf(ledgerClosedResponse.result.ledger_hash, 'string')
assert.typeOf(ledgerClosedResponse.result.ledger_index, 'number')
},
TIMEOUT,
)
})

View File

@@ -1,36 +1,45 @@
import { assert } from 'chai'
import _ from 'lodash'
import { LedgerCurrentResponse, LedgerCurrentRequest } from 'xrpl-local'
import { LedgerCurrentResponse, LedgerCurrentRequest } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('ledger_current', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const ledgerCurrentRequest: LedgerCurrentRequest = {
command: 'ledger_current',
}
const ledgerCurrentResponse = await this.client.request(
ledgerCurrentRequest,
)
const expectedResponse: LedgerCurrentResponse = {
id: ledgerCurrentResponse.id,
type: 'response',
result: {
ledger_current_index: 1,
},
}
assert.equal(ledgerCurrentResponse.type, expectedResponse.type)
assert.typeOf(ledgerCurrentResponse.result.ledger_current_index, 'number')
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const ledgerCurrentRequest: LedgerCurrentRequest = {
command: 'ledger_current',
}
const ledgerCurrentResponse = await testContext.client.request(
ledgerCurrentRequest,
)
const expectedResponse: LedgerCurrentResponse = {
id: ledgerCurrentResponse.id,
type: 'response',
result: {
ledger_current_index: 1,
},
}
assert.equal(ledgerCurrentResponse.type, expectedResponse.type)
assert.typeOf(ledgerCurrentResponse.result.ledger_current_index, 'number')
},
TIMEOUT,
)
})

View File

@@ -1,55 +1,67 @@
import { assert } from 'chai'
import _ from 'lodash'
import { LedgerDataRequest } from 'xrpl-local'
import { LedgerDataRequest } from '../../../src'
import type { BinaryLedgerEntry } from '../../../src/models/methods/ledgerData'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('ledger_data', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const ledgerDataRequest: LedgerDataRequest = {
command: 'ledger_data',
ledger_index: 'validated',
limit: 5,
binary: true,
}
const ledgerDataResponse = await this.client.request(ledgerDataRequest)
const expected = {
id: 0,
result: {
ledger_hash: 'string',
ledger_index: 0,
marker: 'string',
state: [
{
data: 'string',
index: 'string',
},
],
},
type: 'response',
}
assert.equal(ledgerDataResponse.type, expected.type)
assert.typeOf(ledgerDataResponse.result.ledger_hash, 'string')
assert.typeOf(ledgerDataResponse.result.ledger_index, 'number')
assert.typeOf(ledgerDataResponse.result.marker, 'string')
assert.equal(ledgerDataResponse.result.state.length, 5)
ledgerDataResponse.result.state.forEach((item) => {
assert.typeOf(item.data, 'string')
assert.typeOf(item.index, 'string')
})
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const ledgerDataRequest: LedgerDataRequest = {
command: 'ledger_data',
ledger_index: 'validated',
limit: 5,
binary: true,
}
const ledgerDataResponse = await testContext.client.request(
ledgerDataRequest,
)
const expected = {
id: 0,
result: {
ledger_hash: 'string',
ledger_index: 0,
marker: 'string',
state: [
{
data: 'string',
index: 'string',
},
],
},
type: 'response',
}
assert.equal(ledgerDataResponse.type, expected.type)
assert.typeOf(ledgerDataResponse.result.ledger_hash, 'string')
assert.typeOf(ledgerDataResponse.result.ledger_index, 'number')
assert.typeOf(ledgerDataResponse.result.marker, 'string')
assert.equal(ledgerDataResponse.result.state.length, 5)
ledgerDataResponse.result.state.forEach((item) => {
assert.typeOf((item as BinaryLedgerEntry).data, 'string')
assert.typeOf(item.index, 'string')
})
},
TIMEOUT,
)
})

View File

@@ -1,47 +1,58 @@
import { assert } from 'chai'
import _ from 'lodash'
import { LedgerEntryRequest, LedgerEntryResponse } from 'xrpl-local'
import { LedgerEntryRequest, LedgerEntryResponse } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('ledger_entry', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const validatedLedgerResponse = await this.client.request({
command: 'ledger_data',
ledger_index: 'validated',
})
assert.equal(validatedLedgerResponse.type, 'response')
const ledgerEntryIndex = validatedLedgerResponse.result.state[0].index
const ledgerEntryRequest: LedgerEntryRequest = {
command: 'ledger_entry',
index: ledgerEntryIndex,
}
const ledgerEntryResponse = await this.client.request(ledgerEntryRequest)
const expectedResponse: LedgerEntryResponse = {
id: ledgerEntryResponse.id,
type: 'response',
result: {
index: ledgerEntryIndex,
ledger_current_index: ledgerEntryResponse.result.ledger_current_index,
node: ledgerEntryResponse.result.node,
validated: false,
},
}
assert.equal(ledgerEntryResponse.type, 'response')
assert.deepEqual(ledgerEntryResponse, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const validatedLedgerResponse = await testContext.client.request({
command: 'ledger_data',
ledger_index: 'validated',
})
assert.equal(validatedLedgerResponse.type, 'response')
const ledgerEntryIndex = validatedLedgerResponse.result.state[0].index
const ledgerEntryRequest: LedgerEntryRequest = {
command: 'ledger_entry',
index: ledgerEntryIndex,
}
const ledgerEntryResponse = await testContext.client.request(
ledgerEntryRequest,
)
const expectedResponse: LedgerEntryResponse = {
id: ledgerEntryResponse.id,
type: 'response',
result: {
index: ledgerEntryIndex,
ledger_current_index: ledgerEntryResponse.result.ledger_current_index,
node: ledgerEntryResponse.result.node,
validated: false,
},
}
assert.equal(ledgerEntryResponse.type, 'response')
assert.deepEqual(ledgerEntryResponse, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,57 +1,70 @@
import { assert } from 'chai'
import _ from 'lodash'
import { NoRippleCheckRequest } from 'xrpl-local'
import { NoRippleCheckRequest, type AccountSet } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('noripple_check', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const request: NoRippleCheckRequest = {
command: 'noripple_check',
account: this.wallet.classicAddress,
role: 'gateway',
ledger_index: 'current',
transactions: true,
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
ledger_current_index: 2535,
problems: ['You should immediately set your default ripple flag'],
transactions: [
{
Account: this.wallet.classicAddress,
Fee: 10,
Sequence: 1268,
SetFlag: 8,
TransactionType: 'AccountSet',
},
],
validated: false,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.transactions[0].Fee, 'number')
assert.equal(typeof response.result.transactions[0].Sequence, 'number')
assert.equal(typeof response.result.problems, 'object')
assert.equal(typeof response.result.problems[0], 'string')
const responseTx = response.result.transactions[0]
const expectedTx = expected.result.transactions[0]
assert.deepEqual(
[responseTx.Account, responseTx.SetFlag, responseTx.TransactionType],
[expectedTx.Account, expectedTx.SetFlag, expectedTx.TransactionType],
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const request: NoRippleCheckRequest = {
command: 'noripple_check',
account: testContext.wallet.classicAddress,
role: 'gateway',
ledger_index: 'current',
transactions: true,
}
const response = await testContext.client.request(request)
const expected = {
id: 0,
result: {
ledger_current_index: 2535,
problems: ['You should immediately set your default ripple flag'],
transactions: [
{
Account: testContext.wallet.classicAddress,
Fee: 10,
Sequence: 1268,
SetFlag: 8,
TransactionType: 'AccountSet',
},
],
validated: false,
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.transactions[0].Fee, 'number')
assert.equal(typeof response.result.transactions[0].Sequence, 'number')
assert.equal(typeof response.result.problems, 'object')
assert.equal(typeof response.result.problems[0], 'string')
const responseTx = response.result.transactions[0]
const expectedTx = expected.result.transactions[0]
assert.deepEqual(
[
responseTx.Account,
(responseTx as AccountSet).SetFlag,
responseTx.TransactionType,
],
[expectedTx.Account, expectedTx.SetFlag, expectedTx.TransactionType],
)
},
TIMEOUT,
)
})

View File

@@ -1,107 +1,121 @@
import { assert } from 'chai'
import _ from 'lodash'
import omit from 'lodash/omit'
import {
PathFindRequest,
PathFindResponse,
Client,
PathFindStream,
} from 'xrpl-local'
} from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, ledgerAccept, subscribeDone } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('path_find', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const pathFind: PathFindRequest = {
command: 'path_find',
subcommand: 'create',
source_account: this.wallet.classicAddress,
destination_account: wallet2.classicAddress,
destination_amount: '100',
}
const response = await this.client.request(pathFind)
const expectedResponse: PathFindResponse = {
id: response.id,
type: 'response',
result: {
alternatives: response.result.alternatives,
destination_account: pathFind.destination_account,
destination_amount: pathFind.destination_amount,
source_account: pathFind.source_account,
full_reply: false,
id: response.id,
},
}
assert.deepEqual(response, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const pathFind: PathFindRequest = {
command: 'path_find',
subcommand: 'create',
source_account: testContext.wallet.classicAddress,
destination_account: wallet2.classicAddress,
destination_amount: '100',
}
const response = await testContext.client.request(pathFind)
const expectedResponse: PathFindResponse = {
id: response.id,
type: 'response',
result: {
alternatives: response.result.alternatives,
destination_account: pathFind.destination_account,
destination_amount: pathFind.destination_amount,
source_account: pathFind.source_account,
full_reply: false,
id: response.id,
},
}
assert.deepEqual(response, expectedResponse)
},
TIMEOUT,
)
/**
* For other stream style tests look at integration/requests/subscribe.ts
* Note: This test uses '.then' to avoid awaits in order to use 'done' style tests.
*/
it('path_find stream succeeds', function (done) {
generateFundedWallet(this.client)
.then((wallet2) => {
const pathFind: PathFindRequest = {
command: 'path_find',
subcommand: 'create',
source_account: this.wallet.classicAddress,
destination_account: wallet2.classicAddress,
destination_amount: '100',
}
it(
'path_find stream succeeds',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const pathFind: PathFindRequest = {
command: 'path_find',
subcommand: 'create',
source_account: testContext.wallet.classicAddress,
destination_account: wallet2.classicAddress,
destination_amount: '100',
}
const expectedStreamResult: PathFindStream = {
type: 'path_find',
source_account: pathFind.source_account,
destination_account: pathFind.destination_account,
destination_amount: pathFind.destination_amount,
full_reply: true,
id: 10,
alternatives: [],
}
const expectedStreamResult: PathFindStream = {
type: 'path_find',
source_account: pathFind.source_account,
destination_account: pathFind.destination_account,
destination_amount: pathFind.destination_amount,
full_reply: true,
id: 10,
alternatives: [],
}
const client: Client = this.client
const client: Client = testContext.client
const pathFindPromise = new Promise<void>((resolve) => {
client.on('path_find', (path) => {
assert.equal(path.type, 'path_find')
assert.deepEqual(
_.omit(path, 'id'),
_.omit(expectedStreamResult, 'id'),
)
subscribeDone(this.client, done)
})
this.client.request(pathFind).then((response) => {
const expectedResponse: PathFindResponse = {
id: response.id,
type: 'response',
result: {
alternatives: response.result.alternatives,
destination_account: pathFind.destination_account,
destination_amount: pathFind.destination_amount,
source_account: pathFind.source_account,
full_reply: false,
id: response.id,
},
}
assert.deepEqual(response, expectedResponse)
assert.deepEqual(omit(path, 'id'), omit(expectedStreamResult, 'id'))
subscribeDone(testContext.client)
resolve()
})
})
.then(() => {
ledgerAccept(this.client)
})
})
const response = await testContext.client.request(pathFind)
const expectedResponse: PathFindResponse = {
id: response.id,
type: 'response',
result: {
alternatives: response.result.alternatives,
destination_account: pathFind.destination_account,
destination_amount: pathFind.destination_amount,
source_account: pathFind.source_account,
full_reply: false,
id: response.id,
},
}
assert.deepEqual(response, expectedResponse)
await ledgerAccept(testContext.client)
await pathFindPromise
},
TIMEOUT,
)
})

View File

@@ -1,48 +1,57 @@
import { assert } from 'chai'
import _ from 'lodash'
import { RipplePathFindRequest, RipplePathFindResponse } from 'xrpl-local'
import { RipplePathFindRequest, RipplePathFindResponse } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('ripple_path_find', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const ripplePathFind: RipplePathFindRequest = {
command: 'ripple_path_find',
subcommand: 'create',
source_account: this.wallet.classicAddress,
destination_account: wallet2.classicAddress,
destination_amount: '100',
}
const response = await this.client.request(ripplePathFind)
const expectedResponse: RipplePathFindResponse = {
id: response.id,
type: 'response',
result: {
alternatives: response.result.alternatives,
destination_account: wallet2.classicAddress,
destination_currencies: response.result.destination_currencies,
destination_amount: ripplePathFind.destination_amount,
full_reply: true,
id: response.id,
ledger_current_index: response.result.ledger_current_index,
source_account: ripplePathFind.source_account,
validated: false,
},
}
assert.deepEqual(response, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const ripplePathFind: RipplePathFindRequest = {
command: 'ripple_path_find',
subcommand: 'create',
source_account: testContext.wallet.classicAddress,
destination_account: wallet2.classicAddress,
destination_amount: '100',
}
const response = await testContext.client.request(ripplePathFind)
const expectedResponse: RipplePathFindResponse = {
id: response.id,
type: 'response',
result: {
alternatives: response.result.alternatives,
destination_account: wallet2.classicAddress,
destination_currencies: response.result.destination_currencies,
destination_amount: ripplePathFind.destination_amount,
full_reply: true,
id: response.id,
ledger_current_index: response.result.ledger_current_index,
source_account: ripplePathFind.source_account,
validated: false,
},
}
assert.deepEqual(response, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,132 +1,149 @@
import { assert } from 'chai'
import _ from 'lodash'
import { ServerInfoRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { type ServerInfoRequest, type ServerInfoResponse } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('server_info', function () {
this.timeout(TIMEOUT)
describe('server_info (rippled)', function () {
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it('base', async function () {
const request: ServerInfoRequest = {
command: 'server_info',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
info: {
build_version: '1.7.3',
complete_ledgers: '2563-2928',
hostid: '44578fe64241',
io_latency_ms: 1,
jq_trans_overflow: '0',
last_close: { converge_time_s: 0.1, proposers: 0 },
load: {
job_types: [
{
in_progress: 1,
job_type: 'clientCommand',
peak_time: 4,
per_second: 9,
},
{ job_type: 'updatePaths', per_second: 1 },
{ job_type: 'advanceLedger', per_second: 1 },
{ job_type: 'pathFind', per_second: 1 },
{ job_type: 'WriteNode', per_second: 17 },
],
threads: 1,
},
load_factor: 1,
peer_disconnects: '0',
peer_disconnects_resources: '0',
peers: 0,
pubkey_node: 'n9K6DaaReKkCjb9sEfXh5xP3BV9JisrJ9biKB3CSSFXancBnv5cW',
pubkey_validator: 'none',
server_state: 'full',
server_state_duration_us: '8752395105',
state_accounting: {
connected: { duration_us: '0', transitions: 0 },
disconnected: { duration_us: '41860', transitions: 1 },
full: { duration_us: '20723121268', transitions: 1 },
syncing: { duration_us: '0', transitions: 0 },
tracking: { duration_us: '0', transitions: 0 },
},
time: '2021-Sep-23 22:56:55.320858 UTC',
uptime: 8752,
validated_ledger: {
age: 0,
base_fee_xrp: 0.00001,
hash: '532175EC25CF34081D7F83584F37DAB70035A422CBE94352BEDA8EC123CB8F60',
reserve_base_xrp: 200,
reserve_inc_xrp: 50,
seq: 1906,
},
validation_quorum: 0,
validator_list: {
count: 0,
expiration: 'unknown',
status: 'unknown',
it(
'base',
async () => {
const request: ServerInfoRequest = {
command: 'server_info',
}
const response = await testContext.client.request(request)
const expected: ServerInfoResponse = {
id: 0,
result: {
info: {
build_version: '1.7.3',
complete_ledgers: '2563-2928',
hostid: '44578fe64241',
io_latency_ms: 1,
jq_trans_overflow: '0',
last_close: { converge_time_s: 0.1, proposers: 0 },
load: {
job_types: [
{
in_progress: 1,
job_type: 'clientCommand',
peak_time: 4,
per_second: 9,
},
{ job_type: 'updatePaths', per_second: 1 },
{ job_type: 'advanceLedger', per_second: 1 },
{ job_type: 'pathFind', per_second: 1 },
{ job_type: 'WriteNode', per_second: 17 },
],
threads: 1,
},
load_factor: 1,
peer_disconnects: '0',
peer_disconnects_resources: '0',
peers: 0,
pubkey_node: 'n9K6DaaReKkCjb9sEfXh5xP3BV9JisrJ9biKB3CSSFXancBnv5cW',
pubkey_validator: 'none',
server_state: 'full',
server_state_duration_us: '8752395105',
state_accounting: {
connected: { duration_us: '0', transitions: 0 },
disconnected: { duration_us: '41860', transitions: 1 },
full: { duration_us: '20723121268', transitions: 1 },
syncing: { duration_us: '0', transitions: 0 },
tracking: { duration_us: '0', transitions: 0 },
},
time: '2021-Sep-23 22:56:55.320858 UTC',
uptime: 8752,
validated_ledger: {
age: 0,
base_fee_xrp: 0.00001,
hash: '532175EC25CF34081D7F83584F37DAB70035A422CBE94352BEDA8EC123CB8F60',
reserve_base_xrp: 200,
reserve_inc_xrp: 50,
seq: 1906,
},
validation_quorum: 0,
validator_list: {
count: 0,
expiration: 'unknown',
status: 'unknown',
},
},
},
},
type: 'response',
}
assert.equal(response.type, expected.type)
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.info.time, 'string')
assert.equal(typeof response.result.info.uptime, 'number')
assert.equal(typeof response.result.info.complete_ledgers, 'string')
assert.equal(typeof response.result.info.hostid, 'string')
assert.equal(typeof response.result.info.pubkey_node, 'string')
assert.equal(typeof response.result.info.server_state_duration_us, 'string')
const removeKeys = [
'time',
'uptime',
'complete_ledgers',
'hostid',
'load',
'state_accounting',
'pubkey_node',
'server_state_duration_us',
'validated_ledger',
]
assert.deepEqual(
_.omit(response.result.info, removeKeys),
_.omit(expected.result.info, removeKeys),
)
// load
assert.equal(typeof response.result.info.load.threads, 'number')
for (const obj of response.result.info.load.job_types) {
assert.equal(typeof obj.per_second, 'number')
assert.equal(typeof obj.job_type, 'string')
}
// state_accounting
Object.keys(response.result.info.state_accounting).forEach(function (key) {
assert.equal(typeof response.result.info.time, 'string')
assert.equal(typeof response.result.info.uptime, 'number')
assert.equal(typeof response.result.info.complete_ledgers, 'string')
assert.equal(typeof response.result.info.hostid, 'string')
assert.equal(typeof response.result.info.pubkey_node, 'string')
assert.equal(
typeof response.result.info.state_accounting[key].duration_us,
typeof response.result.info.server_state_duration_us,
'string',
)
assert.equal(
typeof response.result.info.state_accounting[key].transitions,
'number',
const removeKeys = [
'time',
'uptime',
'complete_ledgers',
'hostid',
'load',
'state_accounting',
'pubkey_node',
'server_state_duration_us',
'validated_ledger',
]
assert.deepEqual(
omit(response.result.info, removeKeys),
omit(expected.result.info, removeKeys),
)
})
// validated_ledger
assert.equal(typeof response.result.info.validated_ledger.hash, 'string')
for (const key of Object.keys(
_.omit(response.result.info.validated_ledger, 'hash'),
)) {
assert.equal(typeof response.result.info.validated_ledger[key], 'number')
}
})
// load
assert.equal(typeof response.result.info.load?.threads, 'number')
for (const obj of response.result.info.load?.job_types ?? []) {
assert.equal(typeof obj.job_type, 'string')
}
// state_accounting
Object.keys(response.result.info.state_accounting).forEach(function (
key,
) {
assert.equal(
typeof response.result.info.state_accounting[key].duration_us,
'string',
)
assert.equal(
typeof response.result.info.state_accounting[key].transitions,
'number',
)
})
// validated_ledger
assert.equal(typeof response.result.info.validated_ledger?.hash, 'string')
for (const key of Object.keys(
omit(response.result.info.validated_ledger, 'hash'),
)) {
assert.equal(
typeof response.result.info.validated_ledger?.[key],
'number',
)
}
},
TIMEOUT,
)
})

View File

@@ -1,137 +1,156 @@
import { assert } from 'chai'
import _ from 'lodash'
import { ServerStateRequest } from 'xrpl-local'
import omit from 'lodash/omit'
import { type ServerStateRequest, type ServerStateResponse } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('server_state', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it('base', async function () {
const request: ServerStateRequest = {
command: 'server_state',
}
const response = await this.client.request(request)
const expected = {
id: 0,
result: {
state: {
build_version: '1.7.3',
complete_ledgers: '2563-2932',
io_latency_ms: 1,
jq_trans_overflow: '0',
last_close: {
converge_time: 100,
proposers: 0,
it(
'base',
async () => {
const request: ServerStateRequest = {
command: 'server_state',
}
const response = await testContext.client.request(request)
const expected: ServerStateResponse = {
id: 0,
result: {
state: {
build_version: '1.7.3',
complete_ledgers: '2563-2932',
io_latency_ms: 1,
jq_trans_overflow: '0',
last_close: {
converge_time: 100,
proposers: 0,
},
load: {
job_types: [
{
in_progress: 1,
job_type: 'clientCommand',
peak_time: 4,
per_second: 9,
},
{ job_type: 'updatePaths', per_second: 1 },
{ job_type: 'advanceLedger', per_second: 1 },
{ job_type: 'pathFind', per_second: 1 },
{ job_type: 'WriteNode', per_second: 17 },
],
threads: 1,
},
load_base: 256,
load_factor: 256,
load_factor_fee_escalation: 256,
load_factor_fee_queue: 256,
load_factor_fee_reference: 256,
load_factor_server: 256,
peer_disconnects: '0',
peer_disconnects_resources: '0',
peers: 0,
pubkey_node: 'n9K6DaaReKkCjb9sEfXh5xP3BV9JisrJ9biKB3CSSFXancBnv5cW',
pubkey_validator: 'none',
server_state: 'full',
server_state_duration_us: '8752487389',
state_accounting: {
connected: { duration_us: '0', transitions: 0 },
disconnected: { duration_us: '41860', transitions: 1 },
full: { duration_us: '20723121268', transitions: 1 },
syncing: { duration_us: '0', transitions: 0 },
tracking: { duration_us: '0', transitions: 0 },
},
time: '2021-Sep-23 22:56:55.413151 UTC',
uptime: 8752,
validated_ledger: {
base_fee: 10,
close_time: 685829741,
hash: 'B98AABCE40A54DF654C86E56088AD7D46BBA8B8E93AD3FAC2426FEFF847F7937',
reserve_base: 200000000,
reserve_inc: 50000000,
seq: 2294,
},
validation_quorum: 0,
validator_list_expires: 0,
},
load: {
job_types: [
{
in_progress: 1,
job_type: 'clientCommand',
peak_time: 4,
per_second: 9,
},
{ job_type: 'updatePaths', per_second: 1 },
{ job_type: 'advanceLedger', per_second: 1 },
{ job_type: 'pathFind', per_second: 1 },
{ job_type: 'WriteNode', per_second: 17 },
],
threads: 1,
},
load_base: 256,
load_factor: 256,
load_factor_fee_escalation: 256,
load_factor_fee_queue: 256,
load_factor_fee_reference: 256,
load_factor_server: 256,
peer_disconnects: '0',
peer_disconnects_resources: '0',
peers: 0,
pubkey_node: 'n9K6DaaReKkCjb9sEfXh5xP3BV9JisrJ9biKB3CSSFXancBnv5cW',
pubkey_validator: 'none',
server_state: 'full',
server_state_duration_us: '8752487389',
state_accounting: {
connected: { duration_us: '0', transitions: 0 },
disconnected: { duration_us: '41860', transitions: 1 },
full: { duration_us: '20723121268', transitions: 1 },
syncing: { duration_us: '0', transitions: 0 },
tracking: { duration_us: '0', transitions: 0 },
},
time: '2021-Sep-23 22:56:55.413151 UTC',
uptime: 8752,
validated_ledger: {
base_fee: 10,
close_time: 685829741,
hash: 'B98AABCE40A54DF654C86E56088AD7D46BBA8B8E93AD3FAC2426FEFF847F7937',
reserve_base: 200000000,
reserve_inc: 50000000,
seq: 2294,
},
validation_quorum: 0,
validator_list_expires: 0,
},
},
type: 'response',
}
assert.equal(response.type, expected.type)
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(typeof response.result.state.complete_ledgers, 'string')
assert.equal(typeof response.result.state.pubkey_node, 'string')
assert.equal(typeof response.result.state.time, 'string')
assert.equal(typeof response.result.state.uptime, 'number')
assert.equal(
typeof response.result.state.server_state_duration_us,
'string',
)
const removeKeys = [
'complete_ledgers',
'load',
'state_accounting',
'pubkey_node',
'time',
'uptime',
'server_state_duration_us',
'validated_ledger',
]
assert.deepEqual(
_.omit(response.result.state, removeKeys),
_.omit(expected.result.state, removeKeys),
)
// load
assert.equal(typeof response.result.state.load.threads, 'number')
for (const obj of response.result.state.load.job_types) {
assert.equal(typeof obj.per_second, 'number')
assert.equal(typeof obj.job_type, 'string')
}
// state_accounting
Object.keys(response.result.state.state_accounting).forEach(function (key) {
assert.equal(typeof response.result.state.io_latency_ms, 'number')
assert.equal(typeof response.result.state.complete_ledgers, 'string')
assert.equal(typeof response.result.state.pubkey_node, 'string')
assert.equal(typeof response.result.state.time, 'string')
assert.equal(typeof response.result.state.uptime, 'number')
assert.equal(
typeof response.result.state.state_accounting[key].duration_us,
typeof response.result.state.server_state_duration_us,
'string',
)
assert.equal(
typeof response.result.state.state_accounting[key].transitions,
'number',
)
})
// validated_ledger
assert.equal(typeof response.result.state.validated_ledger.hash, 'string')
for (const key of Object.keys(
_.omit(response.result.state.validated_ledger, 'hash'),
)) {
assert.equal(typeof response.result.state.validated_ledger[key], 'number')
}
})
const removeKeys = [
'complete_ledgers',
'load',
'state_accounting',
'pubkey_node',
'time',
'uptime',
'server_state_duration_us',
'validated_ledger',
'io_latency_ms',
]
assert.deepEqual(
omit(response.result.state, removeKeys),
omit(expected.result.state, removeKeys),
)
// load
assert.equal(typeof response.result.state.load?.threads, 'number')
for (const obj of response.result.state.load?.job_types ?? []) {
assert.equal(typeof obj.job_type, 'string')
}
// state_accounting
Object.keys(response.result.state.state_accounting).forEach(function (
key,
) {
assert.equal(
typeof response.result.state.state_accounting[key].duration_us,
'string',
)
assert.equal(
typeof response.result.state.state_accounting[key].transitions,
'number',
)
})
// validated_ledger
assert.equal(
typeof response.result.state.validated_ledger?.hash,
'string',
)
for (const key of Object.keys(
omit(response.result.state.validated_ledger, 'hash'),
)) {
assert.equal(
typeof response.result.state.validated_ledger?.[key],
'number',
)
}
},
TIMEOUT,
)
})

View File

@@ -1,17 +1,20 @@
import { assert } from 'chai'
import _ from 'lodash'
import { decode } from 'ripple-binary-codec/dist'
import { decode } from 'ripple-binary-codec'
import {
AccountSet,
SubmitRequest,
SubmitResponse,
hashes,
Transaction,
} from 'xrpl-local'
import { convertStringToHex } from 'xrpl-local/utils'
} from '../../../src'
import { convertStringToHex } from '../../../src/utils'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { ledgerAccept, verifySubmittedTransaction } from '../utils'
// how long before each test case times out
@@ -19,59 +22,65 @@ const TIMEOUT = 20000
const { hashSignedTx } = hashes
describe('submit', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('submit', async function () {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const autofilledTx = await this.client.autofill(accountSet)
const signedTx = this.wallet.sign(autofilledTx)
const submitRequest: SubmitRequest = {
command: 'submit',
tx_blob: signedTx.tx_blob,
}
const submitResponse = await this.client.request(submitRequest)
await ledgerAccept(this.client)
await verifySubmittedTransaction(
this.client,
signedTx.tx_blob,
signedTx.hash,
)
const expectedResponse: SubmitResponse = {
id: submitResponse.id,
type: 'response',
result: {
engine_result: 'tesSUCCESS',
engine_result_code: 0,
engine_result_message:
'The transaction was applied. Only final in a validated ledger.',
tx_blob: signedTx.tx_blob,
tx_json: {
...(decode(signedTx.tx_blob) as unknown as Transaction),
hash: hashSignedTx(signedTx.tx_blob),
},
accepted: true,
account_sequence_available:
submitResponse.result.account_sequence_available,
account_sequence_next: submitResponse.result.account_sequence_next,
applied: true,
broadcast: submitResponse.result.broadcast,
kept: true,
queued: false,
open_ledger_cost: submitResponse.result.open_ledger_cost,
validated_ledger_index: submitResponse.result.validated_ledger_index,
},
}
assert.deepEqual(submitResponse, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'submit',
async () => {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const autofilledTx = await testContext.client.autofill(accountSet)
const signedTx = testContext.wallet.sign(autofilledTx)
const submitRequest: SubmitRequest = {
command: 'submit',
tx_blob: signedTx.tx_blob,
}
const submitResponse = await testContext.client.request(submitRequest)
await ledgerAccept(testContext.client)
await verifySubmittedTransaction(
testContext.client,
signedTx.tx_blob,
signedTx.hash,
)
const expectedResponse: SubmitResponse = {
id: submitResponse.id,
type: 'response',
result: {
engine_result: 'tesSUCCESS',
engine_result_code: 0,
engine_result_message:
'The transaction was applied. Only final in a validated ledger.',
tx_blob: signedTx.tx_blob,
tx_json: {
...(decode(signedTx.tx_blob) as unknown as Transaction),
hash: hashSignedTx(signedTx.tx_blob),
},
accepted: true,
account_sequence_available:
submitResponse.result.account_sequence_available,
account_sequence_next: submitResponse.result.account_sequence_next,
applied: true,
broadcast: submitResponse.result.broadcast,
kept: true,
queued: false,
open_ledger_cost: submitResponse.result.open_ledger_cost,
validated_ledger_index: submitResponse.result.validated_ledger_index,
},
}
assert.deepEqual(submitResponse, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,6 +1,6 @@
import { assert } from 'chai'
import _ from 'lodash'
import { decode } from 'ripple-binary-codec/dist'
import { decode } from 'ripple-binary-codec'
import {
AccountSet,
Client,
@@ -9,12 +9,15 @@ import {
Transaction,
SubmitMultisignedResponse,
hashes,
} from 'xrpl-local'
import { convertStringToHex } from 'xrpl-local/utils'
import { multisign } from 'xrpl-local/Wallet/signer'
} from '../../../src'
import { convertStringToHex } from '../../../src/utils'
import { multisign } from '../../../src/Wallet/signer'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import {
generateFundedWallet,
ledgerAccept,
@@ -27,73 +30,83 @@ const TIMEOUT = 20000
const { hashSignedTx } = hashes
describe('submit_multisigned', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('submit_multisigned transaction', async function () {
const client: Client = this.client
const signerWallet1 = await generateFundedWallet(this.client)
const signerWallet2 = await generateFundedWallet(this.client)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: this.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: signerWallet1.classicAddress,
SignerWeight: 1,
},
},
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
},
},
],
SignerQuorum: 2,
}
await testTransaction(this.client, signerListSet, this.wallet)
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
const signed1 = signerWallet1.sign(accountSetTx, true)
const signed2 = signerWallet2.sign(accountSetTx, true)
const multisigned = multisign([signed1.tx_blob, signed2.tx_blob])
const multisignedRequest: SubmitMultisignedRequest = {
command: 'submit_multisigned',
tx_json: decode(multisigned) as unknown as Transaction,
}
const submitResponse = await client.request(multisignedRequest)
await ledgerAccept(client)
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
await verifySubmittedTransaction(this.client, multisigned)
const expectedResponse: SubmitMultisignedResponse = {
id: submitResponse.id,
type: 'response',
result: {
engine_result: 'tesSUCCESS',
engine_result_code: 0,
engine_result_message:
'The transaction was applied. Only final in a validated ledger.',
tx_blob: multisigned,
tx_json: {
...(decode(multisigned) as unknown as Transaction),
hash: hashSignedTx(multisigned),
},
},
}
assert.deepEqual(submitResponse, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'submit_multisigned transaction',
async () => {
const client: Client = testContext.client
const signerWallet1 = await generateFundedWallet(testContext.client)
const signerWallet2 = await generateFundedWallet(testContext.client)
// set up the multisigners for the account
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: testContext.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: signerWallet1.classicAddress,
SignerWeight: 1,
},
},
{
SignerEntry: {
Account: signerWallet2.classicAddress,
SignerWeight: 1,
},
},
],
SignerQuorum: 2,
}
await testTransaction(
testContext.client,
signerListSet,
testContext.wallet,
)
// try to multisign
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const accountSetTx = await client.autofill(accountSet, 2)
const signed1 = signerWallet1.sign(accountSetTx, true)
const signed2 = signerWallet2.sign(accountSetTx, true)
const multisigned = multisign([signed1.tx_blob, signed2.tx_blob])
const multisignedRequest: SubmitMultisignedRequest = {
command: 'submit_multisigned',
tx_json: decode(multisigned) as unknown as Transaction,
}
const submitResponse = await client.request(multisignedRequest)
await ledgerAccept(client)
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
await verifySubmittedTransaction(testContext.client, multisigned)
const expectedResponse: SubmitMultisignedResponse = {
id: submitResponse.id,
type: 'response',
result: {
engine_result: 'tesSUCCESS',
engine_result_code: 0,
engine_result_message:
'The transaction was applied. Only final in a validated ledger.',
tx_blob: multisigned,
tx_json: {
...(decode(multisigned) as unknown as Transaction),
hash: hashSignedTx(multisigned),
},
},
}
assert.deepEqual(submitResponse, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,34 +1,38 @@
import { assert } from 'chai'
import _ from 'lodash'
import {
Client,
OfferCreate,
SubscribeRequest,
Wallet,
SubscribeResponse,
} from 'xrpl-local'
import { StreamType } from 'xrpl-local/models/common'
} from '../../../src'
import { StreamType } from '../../../src/models/common'
import type { LedgerStreamResponse } from '../../../src/models/methods/subscribe'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { ledgerAccept, subscribeDone, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
// Note: This test use '.then' to avoid awaits in order to use 'done' style tests.
// eslint-disable-next-line max-params -- Helps keep things well-typed
async function createTxHandlerTest(
client: Client,
wallet: Wallet,
done: Mocha.Done,
subscriptionStream: StreamType,
): Promise<void> {
const txStream = 'transaction'
client.on(txStream, (tx) => {
assert.equal(tx.type, txStream)
subscribeDone(client, done)
const transactionPromise = new Promise<void>((resolve) => {
client.on(txStream, (tx) => {
assert.equal(tx.type, txStream)
subscribeDone(client)
resolve()
})
})
const request: SubscribeRequest = {
@@ -37,17 +41,21 @@ async function createTxHandlerTest(
accounts: [wallet.classicAddress],
}
client.request(request).then((response) => {
assert.equal(response.type, 'response')
assert.deepEqual(response.result, {})
})
const response = await client.request(request)
assert.equal(response.type, 'response')
assert.deepEqual(response.result, {})
return transactionPromise
}
describe('subscribe', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
/**
* Subscribe streams which are not testable with just a standalone node:
@@ -60,17 +68,21 @@ describe('subscribe', function () {
* 'server'.
*/
it('Successfully Subscribes', async function () {
const response: SubscribeResponse = await this.client.request({
command: 'subscribe',
})
it(
'Successfully Subscribes',
async () => {
const response: SubscribeResponse = await testContext.client.request({
command: 'subscribe',
})
assert.deepEqual(response.result, {})
assert.equal(response.type, 'response')
})
assert.deepEqual(response.result, {})
assert.equal(response.type, 'response')
},
TIMEOUT,
)
it('Successfully Unsubscribes', async function () {
const response = await this.client.request({
const response = await testContext.client.request({
command: 'unsubscribe',
})
@@ -78,90 +90,111 @@ describe('subscribe', function () {
assert.equal(response.type, 'response')
})
it('Emits transaction', function (done) {
const streamType = 'transactions'
createTxHandlerTest(this.client, this.wallet, done, streamType).then(() => {
it(
'Emits transaction',
async () => {
const streamType = 'transactions'
const transactionPromise = createTxHandlerTest(
testContext.client,
testContext.wallet,
streamType,
)
// Trigger the event
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: this.wallet.classicAddress,
Account: testContext.wallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: this.wallet.classicAddress,
issuer: testContext.wallet.classicAddress,
value: '10',
},
}
await testTransaction(testContext.client, tx, testContext.wallet)
await transactionPromise
},
TIMEOUT,
)
testTransaction(this.client, tx, this.wallet)
})
})
it(
'Emits transaction on transactions_proposed',
async () => {
const transactionPromise = createTxHandlerTest(
testContext.client,
testContext.wallet,
'transactions_proposed',
)
it('Emits transaction on transactions_proposed', function (done) {
createTxHandlerTest(
this.client,
this.wallet,
done,
'transactions_proposed',
).then(() => {
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: this.wallet.classicAddress,
Account: testContext.wallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: this.wallet.classicAddress,
issuer: testContext.wallet.classicAddress,
value: '10',
},
}
// The transactions_proposed stream should trigger the transaction handler WITHOUT ledgerAccept
const client: Client = this.client
client.submit(tx, { wallet: this.wallet })
})
})
await testContext.client.submit(tx, { wallet: testContext.wallet })
await transactionPromise
},
TIMEOUT,
)
// Note: This test use '.then' to avoid awaits in order to use 'done' style tests.
it('Emits ledger', function (done) {
const request: SubscribeRequest = {
command: 'subscribe',
streams: ['ledger'],
accounts: [this.wallet.classicAddress],
}
this.client.request(request).then((response) => {
// Explicitly checking that there are only known fields in the return
const expectedResult = {
fee_base: response.result.fee_base,
fee_ref: response.result.fee_ref,
ledger_hash: response.result.ledger_hash,
ledger_index: response.result.ledger_index,
ledger_time: response.result.ledger_time,
reserve_base: response.result.reserve_base,
reserve_inc: response.result.reserve_inc,
validated_ledgers: response.result.validated_ledgers,
it(
'Emits ledger',
async () => {
const request: SubscribeRequest = {
command: 'subscribe',
streams: ['ledger'],
accounts: [testContext.wallet.classicAddress],
}
assert.equal(response.type, 'response')
assert.deepEqual(response.result, expectedResult)
await testContext.client.request(request).then(async (response) => {
const ledgerResponse: LedgerStreamResponse =
response.result as LedgerStreamResponse
// Explicitly checking that there are only known fields in the return
const expectedResult = {
fee_base: ledgerResponse.fee_base,
fee_ref: ledgerResponse.fee_ref,
ledger_hash: ledgerResponse.ledger_hash,
ledger_index: ledgerResponse.ledger_index,
ledger_time: ledgerResponse.ledger_time,
reserve_base: ledgerResponse.reserve_base,
reserve_inc: ledgerResponse.reserve_inc,
validated_ledgers: ledgerResponse.validated_ledgers,
}
const client: Client = this.client
client.on('ledgerClosed', (ledger) => {
// Fields that are expected to change between the initial test and now are updated
assert.deepEqual(ledger, {
...expectedResult,
type: 'ledgerClosed',
txn_count: ledger.txn_count,
ledger_hash: ledger.ledger_hash,
ledger_index: parseInt(expectedResult.ledger_index, 10) + 1,
ledger_time: ledger.ledger_time,
validated_ledgers: ledger.validated_ledgers,
assert.equal(response.type, 'response')
assert.deepEqual(response.result, expectedResult)
const client: Client = testContext.client
const ledgerClosedPromise = new Promise<void>((resolve) => {
client.on('ledgerClosed', (ledger) => {
// Fields that are expected to change between the initial test and now are updated
assert.deepEqual(ledger, {
...expectedResult,
type: 'ledgerClosed',
txn_count: ledger.txn_count,
ledger_hash: ledger.ledger_hash,
ledger_index:
parseInt(expectedResult.ledger_index.toString(), 10) + 1,
ledger_time: ledger.ledger_time,
validated_ledgers: ledger.validated_ledgers,
})
subscribeDone(testContext.client)
resolve()
})
})
subscribeDone(this.client, done)
})
// Trigger the event
ledgerAccept(this.client)
})
})
// Trigger the event
await ledgerAccept(testContext.client)
await ledgerClosedPromise
})
},
TIMEOUT,
)
})

View File

@@ -1,55 +1,67 @@
import { assert } from 'chai'
import _ from 'lodash'
import { AccountSet, hashes, SubmitResponse, TxResponse } from 'xrpl-local'
import { convertStringToHex } from 'xrpl-local/utils'
import { AccountSet, hashes, SubmitResponse, TxResponse } from '../../../src'
import { convertStringToHex } from '../../../src/utils'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
const { hashSignedTx } = hashes
describe('tx', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const account = this.wallet.classicAddress
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: account,
Domain: convertStringToHex('example.com'),
}
const response: SubmitResponse = await this.client.submit(accountSet, {
wallet: this.wallet,
})
const hash = hashSignedTx(response.result.tx_blob)
const txResponse = await this.client.request({
command: 'tx',
transaction: hash,
})
const expectedResponse: TxResponse = {
id: txResponse.id,
type: 'response',
result: {
...accountSet,
Fee: txResponse.result.Fee,
Flags: 0,
LastLedgerSequence: txResponse.result.LastLedgerSequence,
Sequence: txResponse.result.Sequence,
SigningPubKey: this.wallet.publicKey,
TxnSignature: txResponse.result.TxnSignature,
hash: hashSignedTx(response.result.tx_blob),
validated: false,
},
}
assert.deepEqual(txResponse, expectedResponse)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const account = testContext.wallet.classicAddress
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: account,
Domain: convertStringToHex('example.com'),
}
const response: SubmitResponse = await testContext.client.submit(
accountSet,
{
wallet: testContext.wallet,
},
)
const hash = hashSignedTx(response.result.tx_blob)
const txResponse = await testContext.client.request({
command: 'tx',
transaction: hash,
})
const expectedResponse: TxResponse = {
id: txResponse.id,
type: 'response',
result: {
...accountSet,
Fee: txResponse.result.Fee,
Flags: 0,
LastLedgerSequence: txResponse.result.LastLedgerSequence,
Sequence: txResponse.result.Sequence,
SigningPubKey: testContext.wallet.publicKey,
TxnSignature: txResponse.result.TxnSignature,
hash: hashSignedTx(response.result.tx_blob),
validated: false,
},
}
assert.deepEqual(txResponse, expectedResponse)
},
TIMEOUT,
)
})

View File

@@ -1,42 +1,55 @@
import { assert } from 'chai'
import _ from 'lodash'
import { Client } from 'xrpl-local'
import omit from 'lodash/omit'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
// how long before each test case times out
const TIMEOUT = 20000
describe('Utility method integration tests', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('ping', async function () {
const response = await (this.client as Client).request({
command: 'ping',
})
const expected: unknown = {
result: { role: 'admin', unlimited: true },
type: 'response',
}
assert.deepEqual(_.omit(response, 'id'), expected)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it('random', async function () {
const response = await (this.client as Client).request({
command: 'random',
})
const expected = {
id: 0,
result: {
random: '[random string of 64 bytes]',
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(response.result.random.length, 64)
})
it(
'ping',
async () => {
const response = await testContext.client.request({
command: 'ping',
})
const expected: unknown = {
result: { role: 'admin', unlimited: true },
type: 'response',
}
assert.deepEqual(omit(response, 'id'), expected)
},
TIMEOUT,
)
it(
'random',
async () => {
const response = await testContext.client.request({
command: 'random',
})
const expected = {
id: 0,
result: {
random: '[random string of 64 bytes]',
},
type: 'response',
}
assert.equal(response.type, expected.type)
assert.equal(response.result.random.length, 64)
},
TIMEOUT,
)
})

View File

@@ -1,26 +1,46 @@
import { Client, Wallet } from 'xrpl-local'
import { Client, Wallet } from '../../src'
import serverUrl from './serverUrl'
import { fundAccount } from './utils'
export async function teardownClient(this: Mocha.Context): Promise<void> {
this.client.removeAllListeners()
this.client.disconnect()
export interface XrplIntegrationTestContext {
client: Client
wallet: Wallet
}
export async function teardownClient(
context: XrplIntegrationTestContext,
): Promise<void> {
context.client.removeAllListeners()
return context.client.disconnect()
}
async function connectWithRetry(client: Client, tries = 0): Promise<void> {
return client.connect().catch(async (error) => {
if (tries < 10) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(connectWithRetry(client, tries + 1))
}, 1000)
})
}
throw error
})
}
export async function setupClient(
this: Mocha.Context,
server = serverUrl,
): Promise<void> {
this.wallet = Wallet.generate()
return new Promise<void>((resolve, reject) => {
this.client = new Client(server)
this.client
.connect()
.then(async () => {
await fundAccount(this.client, this.wallet)
resolve()
})
.catch(reject)
): Promise<XrplIntegrationTestContext> {
const context: XrplIntegrationTestContext = {
client: new Client(server, { timeout: 200000 }),
wallet: Wallet.generate(),
}
return connectWithRetry(context.client).then(async () => {
await fundAccount(context.client, context.wallet, {
count: 20,
delayMs: 1000,
})
return context
})
}

View File

@@ -1,91 +1,149 @@
/* eslint-disable @typescript-eslint/no-misused-promises -- supposed to return a promise here */
/* eslint-disable no-restricted-syntax -- not sure why this rule is here, definitely not needed here */
import { assert } from 'chai'
import _ from 'lodash'
import { AccountSet, convertStringToHex, ValidationError } from 'xrpl-local'
import { AccountSet, convertStringToHex, ValidationError } from '../../src'
import { assertRejects } from '../testUtils'
import serverUrl from './serverUrl'
import { setupClient, teardownClient } from './setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from './setup'
import { ledgerAccept } from './utils'
// how long before each test case times out
const TIMEOUT = 60000
describe('client.submitAndWait', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it('submitAndWait an unsigned transaction', async function () {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const responsePromise = this.client.submitAndWait(accountSet, {
wallet: this.wallet,
async function delayedLedgerAccept(): Promise<unknown> {
await new Promise<void>((resolve) => {
setTimeout(resolve, 1000)
})
const ledgerPromise = setTimeout(ledgerAccept, 1000, this.client)
return Promise.all([responsePromise, ledgerPromise]).then(
([response, _ledger]) => {
assert.equal(response.type, 'response')
assert.equal(response.result.validated, true)
},
)
})
return ledgerAccept(testContext.client)
}
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'),
}
it(
'submitAndWait an unsigned transaction',
async () => {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
await assertRejects(
this.client.submitAndWait(accountSet),
ValidationError,
'Wallet must be provided when submitting an unsigned transaction',
)
})
let retries = 10
it('submitAndWait a signed transaction', async function () {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const { tx_blob: signedAccountSet } = this.wallet.sign(
await this.client.autofill(accountSet),
)
const responsePromise = this.client.submitAndWait(signedAccountSet)
const ledgerPromise = setTimeout(ledgerAccept, 1000, this.client)
return Promise.all([responsePromise, ledgerPromise]).then(
([response, _ledger]) => {
assert.equal(response.type, 'response')
assert.equal(response.result.validated, true)
},
)
})
while (retries > 0) {
retries -= 1
const responsePromise = testContext.client.submitAndWait(accountSet, {
wallet: testContext.wallet,
})
const ledgerPromise = delayedLedgerAccept()
it('submitAndWait a signed transaction longer', async function () {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const { tx_blob: signedAccountSet } = this.wallet.sign(
await this.client.autofill(accountSet),
)
const responsePromise = this.client.submitAndWait(signedAccountSet)
const ledgerPromise = setTimeout(ledgerAccept, 5000, this.client)
return Promise.all([responsePromise, ledgerPromise]).then(
([response, _ledger]) => {
assert.equal(response.type, 'response')
assert.equal(response.result.validated, true)
},
)
})
try {
// eslint-disable-next-line no-await-in-loop -- Testing purposes
const [response, _ledger] = await Promise.all([
responsePromise,
ledgerPromise,
])
assert.equal(response.type, 'response')
assert.equal(response.result.validated, true)
retries = 0
break
} catch (err) {
// eslint-disable-next-line max-depth -- Necessary
if (!(err instanceof Error)) {
throw err
}
const errorCodeRegex = /(?:Preliminary result:\s)(?<errorCode>.*)$/gu
const message = err.message
const matches = errorCodeRegex.exec(message)
const errorCode = matches?.groups?.errorCode
// Retry if another transaction finished before this one
// eslint-disable-next-line max-depth -- Testing
if (['tefPAST_SEQ', 'tefMAX_LEDGER'].includes(errorCode || '')) {
// eslint-disable-next-line no-await-in-loop, no-promise-executor-return -- We are waiting on retries
await new Promise((resolve) => setTimeout(resolve, 1000))
} else {
retries = 0
break
}
}
}
},
TIMEOUT,
)
it(
'should throw a ValidationError when submitting an unsigned transaction without a wallet',
async () => {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
await assertRejects(
testContext.client.submitAndWait(accountSet),
ValidationError,
'Wallet must be provided when submitting an unsigned transaction',
)
},
TIMEOUT,
)
it(
'submitAndWait a signed transaction',
async () => {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const { tx_blob: signedAccountSet } = testContext.wallet.sign(
await testContext.client.autofill(accountSet),
)
const responsePromise = testContext.client.submitAndWait(signedAccountSet)
const ledgerPromise = delayedLedgerAccept()
return Promise.all([responsePromise, ledgerPromise]).then(
([response, _ledger]) => {
assert.equal(response.type, 'response')
assert.equal(response.result.validated, true)
},
)
},
TIMEOUT,
)
it(
'submitAndWait a signed transaction longer',
async () => {
const accountSet: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
Domain: convertStringToHex('example.com'),
}
const { tx_blob: signedAccountSet } = testContext.wallet.sign(
await testContext.client.autofill(accountSet),
)
const responsePromise = testContext.client.submitAndWait(signedAccountSet)
const ledgerPromise = delayedLedgerAccept()
return Promise.all([responsePromise, ledgerPromise]).then(
([response, _ledger]) => {
assert.equal(response.type, 'response')
assert.equal(response.result.validated, true)
},
)
},
TIMEOUT,
)
})

View File

@@ -1,33 +1,64 @@
import _ from 'lodash'
import { AccountDelete } from 'xrpl-local/models/transactions'
import { AccountDelete } from '../../../src/models/transactions'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import { generateFundedWallet, ledgerAccept, testTransaction } from '../utils'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, submitTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('AccountDelete', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
// to the satisfy the condition that account sequence and current ledger_index should be 256 apart.
const promises: Array<Promise<void>> = []
for (let iter = 0; iter < 256; iter += 1) {
promises.push(ledgerAccept(this.client))
}
await Promise.all(promises)
const tx: AccountDelete = {
TransactionType: 'AccountDelete',
Account: this.wallet.classicAddress,
Destination: wallet2.classicAddress,
}
await testTransaction(this.client, tx, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
// to the satisfy the condition that account sequence and current ledger_index should be 256 apart.
// const promises: Array<Promise<void> | Promise<unknown>> = []
// for (let iter = 0; iter < 256; iter += 1) {
// promises.push(ledgerAccept(testContext.client))
// }
// await Promise.all(promises)
const tx: AccountDelete = {
TransactionType: 'AccountDelete',
Account: testContext.wallet.classicAddress,
Destination: wallet2.classicAddress,
}
// Since we are not testing the functionaity of rippled in this library, only that we are submitting commands
// properly, we can just test that the AccountDelete command was successfully received.
await submitTransaction({
client: testContext.client,
transaction: tx,
wallet: testContext.wallet,
})
// TODO: Re-enable this test once we can test the `engine_result` without waiting a significant amount of time.
// Note, we can't test the `engine_result` without waiting a significant
// amount of time because accounts can't be deleted until some number of
// ledgers have closed since its creation.
//
// The documentation for `tecTOO_SOON` reads:
// "The AccountDelete transaction failed because the account to be deleted had a
// Sequence number that is too high. The current ledger index must be at least
// 256 higher than the account's sequence number."
//
// self.assertEqual(response.result['engine_result'], 'tesSUCCESS')
// await testTransaction(testContext.client, tx, testContext.wallet, {
// // Need to retry when running tests concurrently
// count: 5,
// delayMs: 1000,
// })
},
TIMEOUT,
)
})

View File

@@ -1,24 +1,32 @@
import _ from 'lodash'
import { AccountSet } from 'xrpl-local/models/transactions'
import { AccountSet } from '../../../src/models/transactions'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('AccountSet', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const tx: AccountSet = {
TransactionType: 'AccountSet',
Account: this.wallet.classicAddress,
}
await testTransaction(this.client, tx, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const tx: AccountSet = {
TransactionType: 'AccountSet',
Account: testContext.wallet.classicAddress,
}
await testTransaction(testContext.client, tx, testContext.wallet)
},
TIMEOUT,
)
})

View File

@@ -1,63 +1,72 @@
import { assert } from 'chai'
import _ from 'lodash'
import { CheckCreate, CheckCancel } from 'xrpl-local'
import { CheckCreate, CheckCancel } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('CheckCancel', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const setupTx: CheckCreate = {
TransactionType: 'CheckCreate',
Account: this.wallet.classicAddress,
Destination: wallet2.classicAddress,
SendMax: '50',
}
await testTransaction(this.client, setupTx, this.wallet)
// get check ID
const response1 = await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
response1.result.account_objects,
1,
'Should be exactly one check on the ledger',
)
const checkId = response1.result.account_objects[0].index
// actual test - cancel the check
const tx: CheckCancel = {
TransactionType: 'CheckCancel',
Account: this.wallet.classicAddress,
CheckID: checkId,
}
await testTransaction(this.client, tx, this.wallet)
// confirm that the check no longer exists
const accountOffersResponse = await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
accountOffersResponse.result.account_objects,
0,
'Should be no checks on the ledger',
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const setupTx: CheckCreate = {
TransactionType: 'CheckCreate',
Account: testContext.wallet.classicAddress,
Destination: wallet2.classicAddress,
SendMax: '50',
}
await testTransaction(testContext.client, setupTx, testContext.wallet)
// get check ID
const response1 = await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
response1.result.account_objects,
1,
'Should be exactly one check on the ledger',
)
const checkId = response1.result.account_objects[0].index
// actual test - cancel the check
const tx: CheckCancel = {
TransactionType: 'CheckCancel',
Account: testContext.wallet.classicAddress,
CheckID: checkId,
}
await testTransaction(testContext.client, tx, testContext.wallet)
// confirm that the check no longer exists
const accountOffersResponse = await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
accountOffersResponse.result.account_objects,
0,
'Should be no checks on the ledger',
)
},
TIMEOUT,
)
})

View File

@@ -1,66 +1,75 @@
import { assert } from 'chai'
import _ from 'lodash'
import { CheckCreate, CheckCash } from 'xrpl-local'
import { CheckCreate, CheckCash } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('CheckCash', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const amount = '500'
const setupTx: CheckCreate = {
TransactionType: 'CheckCreate',
Account: this.wallet.classicAddress,
Destination: wallet2.classicAddress,
SendMax: amount,
}
await testTransaction(this.client, setupTx, this.wallet)
// get check ID
const response1 = await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
response1.result.account_objects,
1,
'Should be exactly one check on the ledger',
)
const checkId = response1.result.account_objects[0].index
// actual test - cash the check
const tx: CheckCash = {
TransactionType: 'CheckCash',
Account: wallet2.classicAddress,
CheckID: checkId,
Amount: amount,
}
await testTransaction(this.client, tx, wallet2)
// confirm that the check no longer exists
const accountOffersResponse = await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
accountOffersResponse.result.account_objects,
0,
'Should be no checks on the ledger',
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const amount = '500'
const setupTx: CheckCreate = {
TransactionType: 'CheckCreate',
Account: testContext.wallet.classicAddress,
Destination: wallet2.classicAddress,
SendMax: amount,
}
await testTransaction(testContext.client, setupTx, testContext.wallet)
// get check ID
const response1 = await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
response1.result.account_objects,
1,
'Should be exactly one check on the ledger',
)
const checkId = response1.result.account_objects[0].index
// actual test - cash the check
const tx: CheckCash = {
TransactionType: 'CheckCash',
Account: wallet2.classicAddress,
CheckID: checkId,
Amount: amount,
}
await testTransaction(testContext.client, tx, wallet2)
// confirm that the check no longer exists
const accountOffersResponse = await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
accountOffersResponse.result.account_objects,
0,
'Should be no checks on the ledger',
)
},
TIMEOUT,
)
})

View File

@@ -1,41 +1,50 @@
import { assert } from 'chai'
import _ from 'lodash'
import { CheckCreate } from 'xrpl-local'
import { CheckCreate } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('CheckCreate', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const tx: CheckCreate = {
TransactionType: 'CheckCreate',
Account: this.wallet.classicAddress,
Destination: wallet2.classicAddress,
SendMax: '50',
}
await testTransaction(this.client, tx, this.wallet)
// confirm that the check actually went through
const accountOffersResponse = await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
accountOffersResponse.result.account_objects,
1,
'Should be exactly one check on the ledger',
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const tx: CheckCreate = {
TransactionType: 'CheckCreate',
Account: testContext.wallet.classicAddress,
Destination: wallet2.classicAddress,
SendMax: '50',
}
await testTransaction(testContext.client, tx, testContext.wallet)
// confirm that the check actually went through
const accountOffersResponse = await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
type: 'check',
})
assert.lengthOf(
accountOffersResponse.result.account_objects,
1,
'Should be exactly one check on the ledger',
)
},
TIMEOUT,
)
})

View File

@@ -1,27 +1,35 @@
import _ from 'lodash'
import { DepositPreauth, Wallet } from 'xrpl-local'
import { DepositPreauth, Wallet } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { fundAccount, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('DepositPreauth', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = Wallet.generate()
fundAccount(this.client, wallet2)
const tx: DepositPreauth = {
TransactionType: 'DepositPreauth',
Account: this.wallet.classicAddress,
Authorize: wallet2.classicAddress,
}
await testTransaction(this.client, tx, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = Wallet.generate()
await fundAccount(testContext.client, wallet2)
const tx: DepositPreauth = {
TransactionType: 'DepositPreauth',
Account: testContext.wallet.classicAddress,
Authorize: wallet2.classicAddress,
}
await testTransaction(testContext.client, tx, testContext.wallet)
},
TIMEOUT,
)
})

View File

@@ -1,72 +1,125 @@
import { assert } from 'chai'
import _ from 'lodash'
import { EscrowCancel, EscrowCreate } from 'xrpl-local'
import { EscrowCancel, EscrowCreate } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import { generateFundedWallet, getXRPBalance, testTransaction } from '../utils'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import {
// calculateWaitTimeForTransaction,
generateFundedWallet,
// getXRPBalance,
testTransaction,
submitTransaction,
} from '../utils'
// TODO: Fix these tests
// NOTE: Because ledger accept is called among multiple tests, the actual ledger close time is not
// accurate. It can end up very far into the future. This means that the CancelAfter timer can potentially
// need to wait for several minutes to be able to properly complete. Since we are not testing the functionaity
// of rippled in this library, only that we are submitting commands properly, we can just test that the EscrowCancel
// command was successfully received. If in the future we isolate tests to run on their own rippled instance,
// we can uncomment the code in this file to test that the escrow was actually cancelled.
// how long before each test case times out
const TIMEOUT = 20000
const TIMEOUT = 50000
describe('EscrowCancel', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
// get the most recent close_time from the standalone container for cancel & finish after.
const CLOSE_TIME: number = (
await this.client.request({
command: 'ledger',
ledger_index: 'validated',
})
).result.ledger.close_time
const wallet1 = await generateFundedWallet(this.client)
const createTx: EscrowCreate = {
Account: this.wallet.classicAddress,
TransactionType: 'EscrowCreate',
Amount: '10000',
Destination: wallet1.classicAddress,
CancelAfter: CLOSE_TIME + 3,
FinishAfter: CLOSE_TIME + 2,
}
await testTransaction(this.client, createTx, this.wallet)
const initialBalanceWallet1 = await getXRPBalance(this.client, wallet1)
// check that the object was actually created
const accountObjects = (
await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
})
).result.account_objects
assert.equal(accountObjects.length, 1)
const sequence = (
await this.client.request({
command: 'tx',
transaction: accountObjects[0].PreviousTxnID,
})
).result.Sequence
const cancelTx: EscrowCancel = {
TransactionType: 'EscrowCancel',
Account: this.wallet.classicAddress,
Owner: this.wallet.classicAddress,
OfferSequence: sequence,
}
await testTransaction(this.client, cancelTx, this.wallet)
assert.equal(
await getXRPBalance(this.client, wallet1),
initialBalanceWallet1,
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
// Funding the wallet can take some time, so we do it first BEFORE getting the ledger close_time.
const wallet1 = await generateFundedWallet(testContext.client)
// get the most recent close_time from the standalone container for cancel & finish after.
const CLOSE_TIME: number = (
await testContext.client.request({
command: 'ledger',
ledger_index: 'validated',
})
).result.ledger.close_time
// const waitTimeInMs = calculateWaitTimeForTransaction(CLOSE_TIME)
const createTx: EscrowCreate = {
Account: testContext.wallet.classicAddress,
TransactionType: 'EscrowCreate',
Amount: '10000',
Destination: wallet1.classicAddress,
CancelAfter: CLOSE_TIME + 3,
FinishAfter: CLOSE_TIME + 2,
}
await testTransaction(testContext.client, createTx, testContext.wallet)
// const initialBalanceWallet1 = await getXRPBalance(
// testContext.client,
// wallet1,
// )
// check that the object was actually created
const accountObjects = (
await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
})
).result.account_objects
assert.equal(accountObjects.length, 1)
const sequence = (
await testContext.client.request({
command: 'tx',
transaction: accountObjects[0].PreviousTxnID,
})
).result.Sequence
if (!sequence) {
throw new Error('sequence did not exist')
}
const cancelTx: EscrowCancel = {
TransactionType: 'EscrowCancel',
Account: testContext.wallet.classicAddress,
Owner: testContext.wallet.classicAddress,
OfferSequence: sequence,
}
// We set the CancelAfter timer to be 3 seconds after the last ledger close_time. We need to wait this long
// before we can cancel the escrow.
// const cancelAfterTimerPromise = new Promise((resolve) => {
// setTimeout(resolve, waitTimeInMs)
// })
// Make sure we wait long enough before canceling the escrow.
// await cancelAfterTimerPromise
// await testTransaction(testContext.client, cancelTx, testContext.wallet, {
// count: 20,
// delayMs: 2000,
// })
await submitTransaction({
client: testContext.client,
transaction: cancelTx,
wallet: testContext.wallet,
})
// Make sure the Destination wallet did not receive any XRP.
// assert.equal(
// await getXRPBalance(testContext.client, wallet1),
// initialBalanceWallet1,
// )
},
TIMEOUT,
)
})

View File

@@ -1,49 +1,59 @@
import { assert } from 'chai'
import _ from 'lodash'
import { EscrowCreate } from 'xrpl-local'
import { EscrowCreate } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('EscrowCreate', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
// get the most recent close_time from the standalone container for finish after.
const CLOSE_TIME: number = (
await this.client.request({
command: 'ledger',
ledger_index: 'validated',
})
).result.ledger.close_time
const wallet1 = await generateFundedWallet(this.client)
const tx: EscrowCreate = {
Account: this.wallet.classicAddress,
TransactionType: 'EscrowCreate',
Amount: '10000',
Destination: wallet1.classicAddress,
FinishAfter: CLOSE_TIME + 2,
}
await testTransaction(this.client, tx, this.wallet)
// check that the object was actually created
assert.equal(
(
await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
})
).result.account_objects.length,
1,
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
// get the most recent close_time from the standalone container for finish after.
const CLOSE_TIME: number = (
await testContext.client.request({
command: 'ledger',
ledger_index: 'validated',
})
).result.ledger.close_time
const tx: EscrowCreate = {
Account: testContext.wallet.classicAddress,
TransactionType: 'EscrowCreate',
Amount: '10000',
Destination: wallet2.classicAddress,
FinishAfter: CLOSE_TIME + 2,
}
await testTransaction(testContext.client, tx, testContext.wallet)
// check that the object was actually created
assert.equal(
(
await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
})
).result.account_objects.length,
1,
)
},
TIMEOUT,
)
})

View File

@@ -1,71 +1,97 @@
import { assert } from 'chai'
import _ from 'lodash'
import { EscrowFinish, EscrowCreate } from 'xrpl-local'
import { EscrowFinish, EscrowCreate } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import { generateFundedWallet, getXRPBalance, testTransaction } from '../utils'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import {
calculateWaitTimeForTransaction,
generateFundedWallet,
getXRPBalance,
testTransaction,
} from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
const TIMEOUT = 30000
describe('EscrowFinish', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
// get the most recent close_time from the standalone container for cancel & finish after.
const CLOSE_TIME: number = (
await this.client.request({
command: 'ledger',
ledger_index: 'validated',
})
).result.ledger.close_time
const wallet1 = await generateFundedWallet(this.client)
const AMOUNT = 10000
const createTx: EscrowCreate = {
Account: this.wallet.classicAddress,
TransactionType: 'EscrowCreate',
Amount: '10000',
Destination: wallet1.classicAddress,
FinishAfter: CLOSE_TIME + 2,
}
await testTransaction(this.client, createTx, this.wallet)
const initialBalance = await getXRPBalance(this.client, wallet1)
// check that the object was actually created
const accountObjects = (
await this.client.request({
command: 'account_objects',
account: this.wallet.classicAddress,
})
).result.account_objects
assert.equal(accountObjects.length, 1)
const sequence = (
await this.client.request({
command: 'tx',
transaction: accountObjects[0].PreviousTxnID,
})
).result.Sequence
const finishTx: EscrowFinish = {
TransactionType: 'EscrowFinish',
Account: this.wallet.classicAddress,
Owner: this.wallet.classicAddress,
OfferSequence: sequence,
}
await testTransaction(this.client, finishTx, this.wallet)
const expectedBalance = String(Number(initialBalance) + Number(AMOUNT))
assert.equal(await getXRPBalance(this.client, wallet1), expectedBalance)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet1 = await generateFundedWallet(testContext.client)
// get the most recent close_time from the standalone container for cancel & finish after.
const CLOSE_TIME: number = (
await testContext.client.request({
command: 'ledger',
ledger_index: 'validated',
})
).result.ledger.close_time
const waitTimeInMs = calculateWaitTimeForTransaction(CLOSE_TIME)
const AMOUNT = 10000
const createTx: EscrowCreate = {
Account: testContext.wallet.classicAddress,
TransactionType: 'EscrowCreate',
Amount: AMOUNT.toString(),
Destination: wallet1.classicAddress,
FinishAfter: CLOSE_TIME + 2,
}
const finishAfterPromise = new Promise((resolve) => {
setTimeout(resolve, waitTimeInMs)
})
await testTransaction(testContext.client, createTx, testContext.wallet)
const initialBalance = await getXRPBalance(testContext.client, wallet1)
// check that the object was actually created
const accountObjects = (
await testContext.client.request({
command: 'account_objects',
account: testContext.wallet.classicAddress,
})
).result.account_objects
assert.equal(accountObjects.length, 1)
const sequence = (
await testContext.client.request({
command: 'tx',
transaction: accountObjects[0].PreviousTxnID,
})
).result.Sequence
const finishTx: EscrowFinish = {
TransactionType: 'EscrowFinish',
Account: testContext.wallet.classicAddress,
Owner: testContext.wallet.classicAddress,
OfferSequence: sequence!,
}
await finishAfterPromise
await testTransaction(testContext.client, finishTx, testContext.wallet)
const expectedBalance = String(Number(initialBalance) + Number(AMOUNT))
assert.equal(
await getXRPBalance(testContext.client, wallet1),
expectedBalance,
)
},
TIMEOUT,
)
})

View File

@@ -1,63 +1,74 @@
import { assert } from 'chai'
import _ from 'lodash'
import { OfferCreate, OfferCancel } from 'xrpl-local'
import { OfferCreate, OfferCancel } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('OfferCancel', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
// set up an offer
const setupTx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: this.wallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: this.wallet.classicAddress,
value: '10',
},
}
await testTransaction(this.client, setupTx, this.wallet)
const accountOffersResponse = await this.client.request({
command: 'account_offers',
account: this.wallet.classicAddress,
})
assert.lengthOf(
accountOffersResponse.result.offers,
1,
'Should be exactly one offer on the ledger',
)
const seq = accountOffersResponse.result.offers[0].seq
// actually test OfferCancel
const tx: OfferCancel = {
TransactionType: 'OfferCancel',
Account: this.wallet.classicAddress,
OfferSequence: seq,
}
await testTransaction(this.client, tx, this.wallet)
const accountOffersResponse2 = await this.client.request({
command: 'account_offers',
account: this.wallet.classicAddress,
})
assert.lengthOf(
accountOffersResponse2.result.offers,
0,
'Should not be any offers on the ledger',
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
// set up an offer
const setupTx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: testContext.wallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: testContext.wallet.classicAddress,
value: '10',
},
}
await testTransaction(testContext.client, setupTx, testContext.wallet)
const accountOffersResponse = await testContext.client.request({
command: 'account_offers',
account: testContext.wallet.classicAddress,
})
assert.lengthOf(
accountOffersResponse.result.offers!,
1,
'Should be exactly one offer on the ledger',
)
const seq = accountOffersResponse.result.offers?.[0].seq
assert.isNumber(seq)
// actually test OfferCancel
const tx: OfferCancel = {
TransactionType: 'OfferCancel',
Account: testContext.wallet.classicAddress,
OfferSequence: seq!,
}
await testTransaction(testContext.client, tx, testContext.wallet)
const accountOffersResponse2 = await testContext.client.request({
command: 'account_offers',
account: testContext.wallet.classicAddress,
})
assert.lengthOf(
accountOffersResponse2.result.offers!,
0,
'Should not be any offers on the ledger',
)
},
TIMEOUT,
)
})

View File

@@ -1,43 +1,52 @@
import { assert } from 'chai'
import _ from 'lodash'
import { OfferCreate } from 'xrpl-local'
import { OfferCreate } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('OfferCreate', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: this.wallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: this.wallet.classicAddress,
value: '10',
},
}
await testTransaction(this.client, tx, this.wallet)
// confirm that the offer actually went through
const accountOffersResponse = await this.client.request({
command: 'account_offers',
account: this.wallet.classicAddress,
})
assert.lengthOf(
accountOffersResponse.result.offers,
1,
'Should be exactly one offer on the ledger',
)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const tx: OfferCreate = {
TransactionType: 'OfferCreate',
Account: testContext.wallet.classicAddress,
TakerGets: '13100000',
TakerPays: {
currency: 'USD',
issuer: testContext.wallet.classicAddress,
value: '10',
},
}
await testTransaction(testContext.client, tx, testContext.wallet)
// confirm that the offer actually went through
const accountOffersResponse = await testContext.client.request({
command: 'account_offers',
account: testContext.wallet.classicAddress,
})
assert.lengthOf(
accountOffersResponse.result.offers!,
1,
'Should be exactly one offer on the ledger',
)
},
TIMEOUT,
)
})

View File

@@ -1,27 +1,35 @@
import _ from 'lodash'
import { Payment } from 'xrpl-local'
import { Payment } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('Payment', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const tx: Payment = {
TransactionType: 'Payment',
Account: this.wallet.classicAddress,
Destination: wallet2.classicAddress,
Amount: '1000',
}
await testTransaction(this.client, tx, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const tx: Payment = {
TransactionType: 'Payment',
Account: testContext.wallet.classicAddress,
Destination: wallet2.classicAddress,
Amount: '1000',
}
await testTransaction(testContext.client, tx, testContext.wallet)
},
TIMEOUT,
)
})

View File

@@ -1,8 +1,10 @@
import _ from 'lodash'
import { PaymentChannelCreate, hashes, PaymentChannelClaim } from 'xrpl-local'
import { PaymentChannelCreate, hashes, PaymentChannelClaim } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
@@ -10,40 +12,54 @@ const TIMEOUT = 20000
const { hashPaymentChannel } = hashes
describe('PaymentChannelClaim', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate',
Account: this.wallet.classicAddress,
Amount: '100',
Destination: wallet2.classicAddress,
SettleDelay: 86400,
PublicKey: this.wallet.publicKey,
}
const paymentChannelResponse = await this.client.submit(
paymentChannelCreate,
{ wallet: this.wallet },
)
await testTransaction(this.client, paymentChannelCreate, this.wallet)
const paymentChannelClaim: PaymentChannelClaim = {
Account: this.wallet.classicAddress,
TransactionType: 'PaymentChannelClaim',
Channel: hashPaymentChannel(
this.wallet.classicAddress,
wallet2.classicAddress,
paymentChannelResponse.result.tx_json.Sequence ?? 0,
),
Amount: '100',
}
await testTransaction(this.client, paymentChannelClaim, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate',
Account: testContext.wallet.classicAddress,
Amount: '100',
Destination: wallet2.classicAddress,
SettleDelay: 86400,
PublicKey: testContext.wallet.publicKey,
}
const paymentChannelResponse = await testContext.client.submit(
paymentChannelCreate,
{ wallet: testContext.wallet },
)
await testTransaction(
testContext.client,
paymentChannelCreate,
testContext.wallet,
)
const paymentChannelClaim: PaymentChannelClaim = {
Account: testContext.wallet.classicAddress,
TransactionType: 'PaymentChannelClaim',
Channel: hashPaymentChannel(
testContext.wallet.classicAddress,
wallet2.classicAddress,
paymentChannelResponse.result.tx_json.Sequence ?? 0,
),
Amount: '100',
}
await testTransaction(
testContext.client,
paymentChannelClaim,
testContext.wallet,
)
},
TIMEOUT,
)
})

View File

@@ -1,30 +1,42 @@
import _ from 'lodash'
import { PaymentChannelCreate } from 'xrpl-local'
import { PaymentChannelCreate } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('PaymentChannelCreate', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate',
Account: this.wallet.classicAddress,
Amount: '100',
Destination: wallet2.classicAddress,
SettleDelay: 86400,
PublicKey: this.wallet.publicKey,
}
await testTransaction(this.client, paymentChannelCreate, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate',
Account: testContext.wallet.classicAddress,
Amount: '100',
Destination: wallet2.classicAddress,
SettleDelay: 86400,
PublicKey: testContext.wallet.publicKey,
}
await testTransaction(
testContext.client,
paymentChannelCreate,
testContext.wallet,
)
},
TIMEOUT,
)
})

View File

@@ -1,8 +1,10 @@
import _ from 'lodash'
import { PaymentChannelCreate, hashes, PaymentChannelFund } from 'xrpl-local'
import { PaymentChannelCreate, hashes, PaymentChannelFund } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
@@ -10,39 +12,53 @@ const TIMEOUT = 20000
const { hashPaymentChannel } = hashes
describe('PaymentChannelFund', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate',
Account: this.wallet.classicAddress,
Amount: '100',
Destination: wallet2.classicAddress,
SettleDelay: 86400,
PublicKey: this.wallet.publicKey,
}
const paymentChannelResponse = await this.client.submit(
paymentChannelCreate,
{ wallet: this.wallet },
)
await testTransaction(this.client, paymentChannelCreate, this.wallet)
const paymentChannelFund: PaymentChannelFund = {
Account: this.wallet.classicAddress,
TransactionType: 'PaymentChannelFund',
Channel: hashPaymentChannel(
this.wallet.classicAddress,
wallet2.classicAddress,
paymentChannelResponse.result.tx_json.Sequence ?? 0,
),
Amount: '100',
}
await testTransaction(this.client, paymentChannelFund, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate',
Account: testContext.wallet.classicAddress,
Amount: '100',
Destination: wallet2.classicAddress,
SettleDelay: 86400,
PublicKey: testContext.wallet.publicKey,
}
const paymentChannelResponse = await testContext.client.submit(
paymentChannelCreate,
{ wallet: testContext.wallet },
)
await testTransaction(
testContext.client,
paymentChannelCreate,
testContext.wallet,
)
const paymentChannelFund: PaymentChannelFund = {
Account: testContext.wallet.classicAddress,
TransactionType: 'PaymentChannelFund',
Channel: hashPaymentChannel(
testContext.wallet.classicAddress,
wallet2.classicAddress,
paymentChannelResponse.result.tx_json.Sequence ?? 0,
),
Amount: '100',
}
await testTransaction(
testContext.client,
paymentChannelFund,
testContext.wallet,
)
},
TIMEOUT,
)
})

View File

@@ -1,39 +1,47 @@
import _ from 'lodash'
import { SignerListSet } from 'xrpl-local'
import { SignerListSet } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('SignerListSet', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const tx: SignerListSet = {
TransactionType: 'SignerListSet',
Account: this.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: 'r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs',
SignerWeight: 1,
},
},
{
SignerEntry: {
Account: 'r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud',
SignerWeight: 1,
},
},
],
SignerQuorum: 2,
}
await testTransaction(this.client, tx, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it(
'base',
async () => {
const tx: SignerListSet = {
TransactionType: 'SignerListSet',
Account: testContext.wallet.classicAddress,
SignerEntries: [
{
SignerEntry: {
Account: 'r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs',
SignerWeight: 1,
},
},
{
SignerEntry: {
Account: 'r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud',
SignerWeight: 1,
},
},
],
SignerQuorum: 2,
}
await testTransaction(testContext.client, tx, testContext.wallet)
},
TIMEOUT,
)
})

View File

@@ -1,65 +1,81 @@
import _ from 'lodash'
import { TrustSet, percentToQuality } from 'xrpl-local'
import { TrustSet, percentToQuality } from '../../../src'
import serverUrl from '../serverUrl'
import { setupClient, teardownClient } from '../setup'
import {
setupClient,
teardownClient,
type XrplIntegrationTestContext,
} from '../setup'
import { generateFundedWallet, testTransaction } from '../utils'
// how long before each test case times out
const TIMEOUT = 20000
describe('TrustSet', function () {
this.timeout(TIMEOUT)
let testContext: XrplIntegrationTestContext
beforeEach(_.partial(setupClient, serverUrl))
afterEach(teardownClient)
it('base', async function () {
const wallet2 = await generateFundedWallet(this.client)
const tx: TrustSet = {
TransactionType: 'TrustSet',
Account: this.wallet.classicAddress,
LimitAmount: {
currency: 'USD',
issuer: wallet2.classicAddress,
value: '100',
},
}
await testTransaction(this.client, tx, this.wallet)
beforeEach(async () => {
testContext = await setupClient(serverUrl)
})
afterEach(async () => teardownClient(testContext))
it('Quality < 1', async function () {
const wallet2 = await generateFundedWallet(this.client)
const tx: TrustSet = {
TransactionType: 'TrustSet',
Account: this.wallet.address,
QualityIn: percentToQuality('99%'),
QualityOut: percentToQuality('99%'),
LimitAmount: {
currency: 'USD',
issuer: wallet2.address,
value: '100',
},
}
it(
'base',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const tx: TrustSet = {
TransactionType: 'TrustSet',
Account: testContext.wallet.classicAddress,
LimitAmount: {
currency: 'USD',
issuer: wallet2.classicAddress,
value: '100',
},
}
await testTransaction(this.client, tx, this.wallet)
})
await testTransaction(testContext.client, tx, testContext.wallet)
},
TIMEOUT,
)
it('Quality > 1', async function () {
const wallet2 = await generateFundedWallet(this.client)
const tx: TrustSet = {
TransactionType: 'TrustSet',
QualityIn: percentToQuality('101%'),
QualityOut: percentToQuality('101%'),
Account: this.wallet.address,
LimitAmount: {
currency: 'USD',
issuer: wallet2.address,
value: '100',
},
}
it(
'Quality < 1',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const tx: TrustSet = {
TransactionType: 'TrustSet',
Account: testContext.wallet.address,
QualityIn: percentToQuality('99%'),
QualityOut: percentToQuality('99%'),
LimitAmount: {
currency: 'USD',
issuer: wallet2.address,
value: '100',
},
}
await testTransaction(this.client, tx, this.wallet)
})
await testTransaction(testContext.client, tx, testContext.wallet)
},
TIMEOUT,
)
it(
'Quality > 1',
async () => {
const wallet2 = await generateFundedWallet(testContext.client)
const tx: TrustSet = {
TransactionType: 'TrustSet',
QualityIn: percentToQuality('101%'),
QualityOut: percentToQuality('101%'),
Account: testContext.wallet.address,
LimitAmount: {
currency: 'USD',
issuer: wallet2.address,
value: '100',
},
}
await testTransaction(testContext.client, tx, testContext.wallet)
},
TIMEOUT,
)
})

View File

@@ -1,27 +1,173 @@
import { assert } from 'chai'
import _ from 'lodash'
import omit from 'lodash/omit'
import throttle from 'lodash/throttle'
import { decode } from 'ripple-binary-codec'
import { Client, Wallet, AccountInfoRequest } from 'xrpl-local'
import { Payment, Transaction } from 'xrpl-local/models/transactions'
import { hashSignedTx } from 'xrpl-local/utils/hashes'
import {
Client,
Wallet,
AccountInfoRequest,
type SubmitResponse,
TimeoutError,
NotConnectedError,
unixTimeToRippleTime,
} from '../../src'
import { Payment, Transaction } from '../../src/models/transactions'
import { hashSignedTx } from '../../src/utils/hashes'
const masterAccount = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
const masterSecret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb'
export async function ledgerAccept(client: Client): Promise<void> {
const request = { command: 'ledger_accept' }
await client.connection.request(request)
async function sendLedgerAccept(client: Client): Promise<unknown> {
return client.connection.request({ command: 'ledger_accept' })
}
export function subscribeDone(client: Client, done: Mocha.Done): void {
/**
* Throttles an async function in a way that can be awaited.
* By default throttle doesn't return a promise for async functions unless it's invoking them immediately.
*
* @param func - async function to throttle calls for.
* @param wait - same function as lodash.throttle's wait parameter. Call this function at most this often.
* @returns a promise which will be resolved/ rejected only if the function is executed, with the result of the underlying call.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Proper
function asyncThrottle<F extends (...args: any[]) => Promise<unknown>>(
func: F,
wait?: number,
): (...args: Parameters<F>) => ReturnType<F> {
const throttled = throttle((resolve, reject, args: Parameters<F>) => {
func(...args)
.then(resolve)
.catch(reject)
}, wait)
const ret = (...args: Parameters<F>): ReturnType<F> =>
new Promise((resolve, reject) => {
throttled(resolve, reject, args)
}) as ReturnType<F>
return ret
}
const throttledLedgerAccept = asyncThrottle(sendLedgerAccept, 1000)
export async function ledgerAccept(
client: Client,
retries?: number,
shouldThrottle?: boolean,
): Promise<unknown> {
return new Promise<unknown>((resolve, reject) => {
const ledgerAcceptFunc = shouldThrottle
? throttledLedgerAccept
: sendLedgerAccept
ledgerAcceptFunc(client)
.then(resolve)
.catch((error) => {
if (retries === undefined) {
setTimeout(() => {
resolve(ledgerAccept(client, 10))
}, 1000)
} else if (retries > 0) {
setTimeout(() => {
resolve(ledgerAccept(client, retries - 1))
}, 1000)
} else {
reject(error)
}
})
})
}
/**
* Attempt to get the time after which we can check for the escrow to be finished.
* Sometimes the ledger close_time is in the future, so we need to wait for it to catch up.
*
* @param targetTime - The target wait time, before accounting for current ledger time.
* @param minimumWaitTimeMs - The minimum wait time in milliseconds.
* @param maximumWaitTimeMs - The maximum wait time in milliseconds.
* @returns The wait time in milliseconds.
*/
export function calculateWaitTimeForTransaction(
targetTime: number,
minimumWaitTimeMs = 5000,
maximumWaitTimeMs = 20000,
): number {
const currentTimeUnixMs = Math.floor(new Date().getTime())
const currentTimeRippleSeconds = unixTimeToRippleTime(currentTimeUnixMs)
const closeTimeCurrentTimeDiffSeconds = currentTimeRippleSeconds - targetTime
const closeTimeCurrentTimeDiffMs = closeTimeCurrentTimeDiffSeconds * 1000
return Math.max(
minimumWaitTimeMs,
Math.min(
Math.abs(closeTimeCurrentTimeDiffMs) + minimumWaitTimeMs,
// Maximum wait time of 20 seconds
maximumWaitTimeMs,
),
)
}
export function subscribeDone(client: Client): void {
client.removeAllListeners()
done()
}
export async function submitTransaction({
client,
transaction,
wallet,
retry = { count: 5, delayMs: 1000 },
}: {
client: Client
transaction: Transaction
wallet: Wallet
retry?: {
count: number
delayMs: number
}
}): Promise<SubmitResponse> {
let response: SubmitResponse
try {
response = await client.submit(transaction, { wallet })
// Retry if another transaction finished before this one
while (
['tefPAST_SEQ', 'tefMAX_LEDGER'].includes(
response.result.engine_result,
) &&
retry.count > 0
) {
// eslint-disable-next-line no-param-reassign -- we want to decrement the count
retry.count -= 1
// eslint-disable-next-line no-await-in-loop, no-promise-executor-return -- We are waiting on retries
await new Promise((resolve) => setTimeout(resolve, retry.delayMs))
// eslint-disable-next-line no-await-in-loop -- We are retrying in a loop on purpose
response = await client.submit(transaction, { wallet })
}
} catch (error) {
if (error instanceof TimeoutError || error instanceof NotConnectedError) {
// retry
return submitTransaction({
client,
transaction,
wallet,
retry: {
...retry,
count: retry.count > 0 ? retry.count - 1 : 0,
},
})
}
throw error
}
return response
}
export async function fundAccount(
client: Client,
wallet: Wallet,
): Promise<void> {
retry?: {
count: number
delayMs: number
},
): Promise<SubmitResponse> {
const payment: Payment = {
TransactionType: 'Payment',
Account: masterAccount,
@@ -29,17 +175,23 @@ export async function fundAccount(
// 2 times the amount needed for a new account (20 XRP)
Amount: '400000000',
}
const response = await client.submit(payment, {
wallet: Wallet.fromSeed(masterSecret),
const wal = Wallet.fromSeed(masterSecret)
const response = await submitTransaction({
client,
wallet: wal,
transaction: payment,
retry,
})
if (response.result.engine_result !== 'tesSUCCESS') {
// eslint-disable-next-line no-console -- happens only when something goes wrong
console.log(response)
assert.fail(`Response not successful, ${response.result.engine_result}`)
}
await ledgerAccept(client)
const signedTx = _.omit(response.result.tx_json, 'hash')
const signedTx = omit(response.result.tx_json, 'hash')
await verifySubmittedTransaction(client, signedTx as Transaction)
return response
}
export async function generateFundedWallet(client: Client): Promise<Wallet> {
@@ -61,7 +213,7 @@ export async function verifySubmittedTransaction(
assert(data.result)
assert.deepEqual(
_.omit(data.result, [
omit(data.result, [
'date',
'hash',
'inLedger',
@@ -78,19 +230,53 @@ export async function verifySubmittedTransaction(
}
}
/**
* Sends a test transaction for integration testing.
*
* @param client - The XRPL client
* @param transaction - The transaction object to send.
* @param wallet - The wallet to send the transaction from.
* @param retry - As of Sep 2022, xrpl.js does not track requests sent in parallel. Our sequence numbers can get off from
* the server's sequence numbers. This is a fix to retry the transaction if it fails due to tefPAST_SEQ.
* @param retry.count - How many times the request should be retried.
* @param retry.delayMs - How long to wait between retries.
* @returns The response of the transaction.
*/
// eslint-disable-next-line max-params -- Test function, many params are needed
export async function testTransaction(
client: Client,
transaction: Transaction,
wallet: Wallet,
): Promise<void> {
retry?: {
count: number
delayMs: number
},
): Promise<SubmitResponse> {
// Accept any un-validated changes.
await ledgerAccept(client)
// sign/submit the transaction
const response = await client.submit(transaction, { wallet })
const response = await submitTransaction({
client,
wallet,
transaction,
retry,
})
// check that the transaction was successful
assert.equal(response.type, 'response')
if (response.result.engine_result !== 'tesSUCCESS') {
// eslint-disable-next-line no-console -- See output
console.error(
`Transaction was not successful. Expected response.result.engine_result to be tesSUCCESS but got ${response.result.engine_result}`,
)
// eslint-disable-next-line no-console -- See output
console.error('The transaction was: ', transaction)
// eslint-disable-next-line no-console -- See output
console.error('The response was: ', JSON.stringify(response))
}
assert.equal(
response.result.engine_result,
'tesSUCCESS',
@@ -98,9 +284,10 @@ export async function testTransaction(
)
// check that the transaction is on the ledger
const signedTx = _.omit(response.result.tx_json, 'hash')
const signedTx = omit(response.result.tx_json, 'hash')
await ledgerAccept(client)
await verifySubmittedTransaction(client, signedTx as Transaction)
return response
}
export async function getXRPBalance(

View File

@@ -1,5 +1,4 @@
/* eslint-disable consistent-default-export-name/default-export-match-filename -- This is a test file. */
import { Wallet } from 'xrpl-local'
import { Wallet } from '../../src'
const walletSecret = 'shK6YXzwYfnFVn3YZSaMh5zuAddKx'