mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-09 07:15:48 +00:00
test: SignerListSet transaction integration tests (#1621)
* add tests * clean up helper functions * fix account funding * remove unneeded method * use new wallets for each test * automatically fund wallets * fix TODO
This commit is contained in:
@@ -86,7 +86,7 @@
|
||||
"docgen": "typedoc ./src/index.ts",
|
||||
"prepublish": "run-s clean build",
|
||||
"test": "nyc mocha --config=test/.mocharc.json --exit",
|
||||
"test:integration": "TS_NODE_PROJECT=tsconfig.build.json nyc mocha ./test/integration/*.ts",
|
||||
"test:integration": "TS_NODE_PROJECT=tsconfig.build.json nyc mocha ./test/integration/**/*.ts ./test/integration/*.ts",
|
||||
"test:browser": "TS_NODE_PROJECT=tsconfig.build.json nyc mocha ./test/browser/*.ts",
|
||||
"test:watch": "TS_NODE_PROJECT=src/tsconfig.json mocha --config=test/.mocharc.json --watch --reporter dot",
|
||||
"format": "prettier --write '{src,test}/**/*.ts'",
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import assert from 'assert'
|
||||
|
||||
import _ from 'lodash'
|
||||
import { decode } from 'ripple-binary-codec'
|
||||
|
||||
import { Client, Wallet, Transaction } from 'xrpl-local'
|
||||
import { Client, Wallet } from 'xrpl-local'
|
||||
import { AccountSet, SignerListSet } from 'xrpl-local/models/transactions'
|
||||
import { convertStringToHex } from 'xrpl-local/utils'
|
||||
import { sign, multisign } from 'xrpl-local/wallet/signer'
|
||||
@@ -11,10 +10,10 @@ import { sign, multisign } from 'xrpl-local/wallet/signer'
|
||||
import serverUrl from './serverUrl'
|
||||
import { setupClient, suiteClientSetup, teardownClient } from './setup'
|
||||
import {
|
||||
fundAccount,
|
||||
ledgerAccept,
|
||||
testTransaction,
|
||||
verifySubmittedTransaction,
|
||||
fundAccount,
|
||||
} from './utils'
|
||||
|
||||
// how long before each test case times out
|
||||
@@ -33,71 +32,46 @@ describe('integration tests', function () {
|
||||
|
||||
it('submit multisigned transaction', async function () {
|
||||
const client: Client = this.client
|
||||
const multisignAccount = 'r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs'
|
||||
const multisignSecret = 'ss6F8381Br6wwpy9p582H8sBt19J3'
|
||||
const signer1address = 'rQDhz2ZNXmhxzCYwxU6qAbdxsHA4HV45Y2'
|
||||
const signer1secret = 'shK6YXzwYfnFVn3YZSaMh5zuAddKx'
|
||||
const signer2address = 'r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud'
|
||||
const signer2secret = 'shUHQnL4EH27V4EiBrj6EfhWvZngF'
|
||||
await fundAccount(client, multisignAccount)
|
||||
|
||||
const ledgerResponse = await client.request({
|
||||
command: 'ledger',
|
||||
ledger_index: 'validated',
|
||||
})
|
||||
const minLedgerVersion = ledgerResponse.result.ledger_index
|
||||
const signerWallet1 = Wallet.generate()
|
||||
await fundAccount(client, signerWallet1)
|
||||
const signerWallet2 = Wallet.generate()
|
||||
await fundAccount(client, signerWallet2)
|
||||
|
||||
// set up the multisigners for the account
|
||||
const signerListSet: SignerListSet = {
|
||||
TransactionType: 'SignerListSet',
|
||||
Account: multisignAccount,
|
||||
Account: this.wallet.getClassicAddress(),
|
||||
SignerEntries: [
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: signer1address,
|
||||
Account: signerWallet1.getClassicAddress(),
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: signer2address,
|
||||
Account: signerWallet2.getClassicAddress(),
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
SignerQuorum: 2,
|
||||
}
|
||||
const tx = await client.autofill(signerListSet, 2)
|
||||
await testTransaction(
|
||||
this,
|
||||
minLedgerVersion,
|
||||
tx,
|
||||
multisignAccount,
|
||||
multisignSecret,
|
||||
)
|
||||
await testTransaction(this.client, signerListSet, this.wallet)
|
||||
|
||||
// try to multisign
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: multisignAccount,
|
||||
Account: this.wallet.getClassicAddress(),
|
||||
Domain: convertStringToHex('example.com'),
|
||||
}
|
||||
const accountSetTx = await client.autofill(accountSet, 2)
|
||||
const signed1 = sign(Wallet.fromSeed(signer1secret), accountSetTx, true)
|
||||
const signed2 = sign(Wallet.fromSeed(signer2secret), accountSetTx, true)
|
||||
const signed1 = sign(signerWallet1, accountSetTx, true)
|
||||
const signed2 = sign(signerWallet2, accountSetTx, true)
|
||||
const combined = multisign([signed1, signed2])
|
||||
// TODO: replace with `client.submitSignedTransaction`
|
||||
const submitResponse = await client.request({
|
||||
command: 'submit',
|
||||
tx_blob: combined,
|
||||
})
|
||||
const submitResponse = await client.submitSignedTransaction(combined)
|
||||
await ledgerAccept(client)
|
||||
assert.strictEqual(submitResponse.result.engine_result, 'tesSUCCESS')
|
||||
const options = { minLedgerVersion }
|
||||
await verifySubmittedTransaction(
|
||||
this,
|
||||
decode(combined) as unknown as Transaction,
|
||||
options,
|
||||
)
|
||||
await verifySubmittedTransaction(this.client, combined)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('Utility method integration tests', function () {
|
||||
status: 'success',
|
||||
type: 'response',
|
||||
}
|
||||
assert.deepEqual(response, expected)
|
||||
assert.deepEqual(_.omit(response, 'id'), _.omit(expected, 'id'))
|
||||
})
|
||||
|
||||
it('random', async function () {
|
||||
@@ -41,7 +41,6 @@ describe('Utility method integration tests', function () {
|
||||
status: 'success',
|
||||
type: 'response',
|
||||
}
|
||||
assert.equal(response.id, expected.id)
|
||||
assert.equal(response.status, expected.status)
|
||||
assert.equal(response.type, expected.type)
|
||||
assert.equal(response.result.random.length, 64)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { generateXAddress, Client } from 'xrpl-local'
|
||||
import { generateXAddress, Client, Wallet } from 'xrpl-local'
|
||||
|
||||
import serverUrl from './serverUrl'
|
||||
import { ledgerAccept } from './utils'
|
||||
import { fundAccount, ledgerAccept } from './utils'
|
||||
|
||||
export async function teardownClient(this: Mocha.Context): Promise<void> {
|
||||
this.client.disconnect()
|
||||
@@ -29,8 +29,15 @@ 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(resolve).catch(reject)
|
||||
this.client
|
||||
.connect()
|
||||
.then(async () => {
|
||||
await fundAccount(this.client, this.wallet)
|
||||
resolve()
|
||||
})
|
||||
.catch(reject)
|
||||
})
|
||||
}
|
||||
|
||||
40
test/integration/transactions/signerListSet.ts
Normal file
40
test/integration/transactions/signerListSet.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import _ from 'lodash'
|
||||
import { SignerListSet } from 'xrpl-local/models/transactions'
|
||||
|
||||
import serverUrl from '../serverUrl'
|
||||
import { setupClient, suiteClientSetup, teardownClient } from '../setup'
|
||||
import { testTransaction } from '../utils'
|
||||
|
||||
// how long before each test case times out
|
||||
const TIMEOUT = 20000
|
||||
|
||||
describe('SignerListSet', function () {
|
||||
this.timeout(TIMEOUT)
|
||||
|
||||
before(suiteClientSetup)
|
||||
beforeEach(_.partial(setupClient, serverUrl))
|
||||
afterEach(teardownClient)
|
||||
|
||||
it('base', async function () {
|
||||
const tx: SignerListSet = {
|
||||
TransactionType: 'SignerListSet',
|
||||
Account: this.wallet.getClassicAddress(),
|
||||
SignerEntries: [
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: 'r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs',
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: 'r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud',
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
SignerQuorum: 2,
|
||||
}
|
||||
await testTransaction(this.client, tx, this.wallet)
|
||||
})
|
||||
})
|
||||
@@ -3,16 +3,9 @@ import { assert } from 'chai'
|
||||
import _ from 'lodash'
|
||||
import { decode } from 'ripple-binary-codec'
|
||||
|
||||
import { Client, SubmitResponse, Wallet } from 'xrpl-local'
|
||||
import {
|
||||
validatePayment,
|
||||
Payment,
|
||||
Transaction,
|
||||
} from 'xrpl-local/models/transactions'
|
||||
import { Client, Wallet } from 'xrpl-local'
|
||||
import { Payment, Transaction } from 'xrpl-local/models/transactions'
|
||||
import { computeSignedTransactionHash } from 'xrpl-local/utils/hashes'
|
||||
import { sign } from 'xrpl-local/wallet/signer'
|
||||
|
||||
import { walletAddress, walletSecret } from './wallet'
|
||||
|
||||
const masterAccount = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
|
||||
const masterSecret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb'
|
||||
@@ -22,33 +15,21 @@ export async function ledgerAccept(client: Client): Promise<void> {
|
||||
await client.connection.request(request)
|
||||
}
|
||||
|
||||
// TODO: replace with `client.submitTransaction` once that has been merged
|
||||
export async function submitTransaction(
|
||||
client: Client,
|
||||
secret: string,
|
||||
transaction: Transaction,
|
||||
): Promise<SubmitResponse> {
|
||||
const wallet = Wallet.fromSeed(secret)
|
||||
const tx = await client.autofill(transaction)
|
||||
const signedTxEncoded: string = sign(wallet, tx)
|
||||
return client.request({ command: 'submit', tx_blob: signedTxEncoded })
|
||||
}
|
||||
|
||||
export async function fundAccount(
|
||||
client: Client,
|
||||
account: string,
|
||||
wallet: Wallet,
|
||||
): Promise<void> {
|
||||
const payment: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: masterAccount,
|
||||
Destination: account,
|
||||
Destination: wallet.getClassicAddress(),
|
||||
// 2 times the amount needed for a new account (20 XRP)
|
||||
Amount: '400000000',
|
||||
}
|
||||
const paymentTx = await client.autofill(payment)
|
||||
validatePayment(paymentTx)
|
||||
|
||||
const response = await submitTransaction(client, masterSecret, paymentTx)
|
||||
const response = await client.submitTransaction(
|
||||
Wallet.fromSeed(masterSecret),
|
||||
payment,
|
||||
)
|
||||
if (response.result.engine_result !== 'tesSUCCESS') {
|
||||
// eslint-disable-next-line no-console -- happens only when something goes wrong
|
||||
console.log(response)
|
||||
@@ -59,16 +40,13 @@ export async function fundAccount(
|
||||
}
|
||||
|
||||
export async function verifySubmittedTransaction(
|
||||
testcase: Mocha.Context,
|
||||
tx: Transaction,
|
||||
options: { minLedgerVersion: number; maxLedgerVersion?: number },
|
||||
client: Client,
|
||||
tx: Transaction | string,
|
||||
): Promise<void> {
|
||||
const hash = computeSignedTransactionHash(tx)
|
||||
const data = await testcase.client.request({
|
||||
const data = await client.request({
|
||||
command: 'tx',
|
||||
transaction: hash,
|
||||
min_ledger: options.minLedgerVersion,
|
||||
max_ledger: options.maxLedgerVersion,
|
||||
})
|
||||
|
||||
assert(data.result)
|
||||
@@ -81,46 +59,30 @@ export async function verifySubmittedTransaction(
|
||||
'meta',
|
||||
'validated',
|
||||
]),
|
||||
tx,
|
||||
typeof tx === 'string' ? decode(tx) : tx,
|
||||
)
|
||||
if (typeof data.result.meta === 'object') {
|
||||
assert.strictEqual(data.result.meta.TransactionResult, 'tesSUCCESS')
|
||||
} else {
|
||||
assert.strictEqual(data.result.meta, 'tesSUCCESS')
|
||||
}
|
||||
if (testcase.transactions != null) {
|
||||
testcase.transactions.push(hash)
|
||||
}
|
||||
}
|
||||
|
||||
export async function testTransaction(
|
||||
testcase: Mocha.Context,
|
||||
lastClosedLedgerVersion: number,
|
||||
txData: Transaction,
|
||||
address = walletAddress,
|
||||
secret = walletSecret,
|
||||
client: Client,
|
||||
transaction: Transaction,
|
||||
wallet: Wallet,
|
||||
): Promise<void> {
|
||||
assert.strictEqual(txData.Account, address)
|
||||
const client: Client = testcase.client
|
||||
const signedData = sign(Wallet.fromSeed(secret), txData)
|
||||
// sign/submit the transaction
|
||||
const response = await client.submitTransaction(wallet, transaction)
|
||||
|
||||
const attemptedResponse = await client.request({
|
||||
command: 'submit',
|
||||
tx_blob: signedData,
|
||||
})
|
||||
const submittedResponse = testcase.test?.title.includes('multisign')
|
||||
? await ledgerAccept(client).then(() => attemptedResponse)
|
||||
: attemptedResponse
|
||||
// check that the transaction was successful
|
||||
assert.equal(response.status, 'success')
|
||||
assert.equal(response.type, 'response')
|
||||
assert.equal(response.result.engine_result, 'tesSUCCESS')
|
||||
|
||||
assert.strictEqual(submittedResponse.result.engine_result, 'tesSUCCESS')
|
||||
const options = {
|
||||
minLedgerVersion: lastClosedLedgerVersion,
|
||||
maxLedgerVersion: txData.LastLedgerSequence,
|
||||
}
|
||||
await ledgerAccept(testcase.client)
|
||||
await verifySubmittedTransaction(
|
||||
testcase,
|
||||
decode(signedData) as unknown as Transaction,
|
||||
options,
|
||||
)
|
||||
// check that the transaction is on the ledger
|
||||
const signedTx = _.omit(response.result.tx_json, 'hash')
|
||||
await ledgerAccept(client)
|
||||
await verifySubmittedTransaction(client, signedTx as Transaction)
|
||||
}
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
export const walletAddress = 'rQDhz2ZNXmhxzCYwxU6qAbdxsHA4HV45Y2'
|
||||
export const walletSecret = 'shK6YXzwYfnFVn3YZSaMh5zuAddKx'
|
||||
import { Wallet } from 'xrpl-local'
|
||||
|
||||
const walletSecret = 'shK6YXzwYfnFVn3YZSaMh5zuAddKx'
|
||||
|
||||
export const wallet = Wallet.fromSeed(walletSecret)
|
||||
|
||||
Reference in New Issue
Block a user