From 9e39bb25aa4a83da817e6918b69ecd854ab406f0 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 17 Sep 2021 10:35:17 -0400 Subject: [PATCH] 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 --- package.json | 2 +- test/integration/integration.ts | 56 ++++-------- test/integration/requests/utility.ts | 3 +- test/integration/setup.ts | 13 ++- .../integration/transactions/signerListSet.ts | 40 +++++++++ test/integration/utils.ts | 88 ++++++------------- test/integration/wallet.ts | 7 +- 7 files changed, 97 insertions(+), 112 deletions(-) create mode 100644 test/integration/transactions/signerListSet.ts diff --git a/package.json b/package.json index b684c9b1..c847e331 100644 --- a/package.json +++ b/package.json @@ -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'", diff --git a/test/integration/integration.ts b/test/integration/integration.ts index 6962bfa8..b7a57a9f 100644 --- a/test/integration/integration.ts +++ b/test/integration/integration.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) }) }) diff --git a/test/integration/requests/utility.ts b/test/integration/requests/utility.ts index 365afdbd..e6167f9f 100644 --- a/test/integration/requests/utility.ts +++ b/test/integration/requests/utility.ts @@ -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) diff --git a/test/integration/setup.ts b/test/integration/setup.ts index 864873d6..63046b3f 100644 --- a/test/integration/setup.ts +++ b/test/integration/setup.ts @@ -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 { this.client.disconnect() @@ -29,8 +29,15 @@ export async function setupClient( this: Mocha.Context, server = serverUrl, ): Promise { + this.wallet = Wallet.generate() return new Promise((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) }) } diff --git a/test/integration/transactions/signerListSet.ts b/test/integration/transactions/signerListSet.ts new file mode 100644 index 00000000..61492a3f --- /dev/null +++ b/test/integration/transactions/signerListSet.ts @@ -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) + }) +}) diff --git a/test/integration/utils.ts b/test/integration/utils.ts index f2b58ea7..00e250fc 100644 --- a/test/integration/utils.ts +++ b/test/integration/utils.ts @@ -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 { 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 { - 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 { 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 { 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 { - 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) } diff --git a/test/integration/wallet.ts b/test/integration/wallet.ts index d40e5c65..b86bdcc4 100644 --- a/test/integration/wallet.ts +++ b/test/integration/wallet.ts @@ -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)