build: Initial linting setup (#1560)

* sets up linting config and runs `yarn lint --fix` once, so that all changes will show up correctly in future PRs.

* Note that there are still a lot of linter errors.
This commit is contained in:
Nathan Nichols
2021-08-26 21:22:40 -05:00
committed by Mayukha Vadari
parent 12cfed5c17
commit 8b95ee5fab
286 changed files with 15508 additions and 12691 deletions

View File

@@ -1,37 +1,38 @@
import assert from 'assert-diff'
import {ExponentialBackoff} from '../src/client/backoff'
import assert from "assert-diff";
describe('ExponentialBackoff', function () {
it('duration() return value starts with the min value', function () {
import { ExponentialBackoff } from "../src/client/backoff";
describe("ExponentialBackoff", function () {
it("duration() return value starts with the min value", function () {
// default: 100ms
assert(new ExponentialBackoff().duration(), 100)
assert(new ExponentialBackoff({min: 100}).duration(), 100)
assert(new ExponentialBackoff({min: 123}).duration(), 123)
})
assert(new ExponentialBackoff().duration(), 100);
assert(new ExponentialBackoff({ min: 100 }).duration(), 100);
assert(new ExponentialBackoff({ min: 123 }).duration(), 123);
});
it('duration() return value increases when called multiple times', function () {
const backoff = new ExponentialBackoff({min: 100, max: 1000})
assert.strictEqual(backoff.duration(), 100)
assert.strictEqual(backoff.duration(), 200)
assert.strictEqual(backoff.duration(), 400)
assert.strictEqual(backoff.duration(), 800)
})
it("duration() return value increases when called multiple times", function () {
const backoff = new ExponentialBackoff({ min: 100, max: 1000 });
assert.strictEqual(backoff.duration(), 100);
assert.strictEqual(backoff.duration(), 200);
assert.strictEqual(backoff.duration(), 400);
assert.strictEqual(backoff.duration(), 800);
});
it('duration() never returns greater than the max value', function () {
const backoff = new ExponentialBackoff({min: 300, max: 1000})
assert.strictEqual(backoff.duration(), 300)
assert.strictEqual(backoff.duration(), 600)
assert.strictEqual(backoff.duration(), 1000)
assert.strictEqual(backoff.duration(), 1000)
})
it("duration() never returns greater than the max value", function () {
const backoff = new ExponentialBackoff({ min: 300, max: 1000 });
assert.strictEqual(backoff.duration(), 300);
assert.strictEqual(backoff.duration(), 600);
assert.strictEqual(backoff.duration(), 1000);
assert.strictEqual(backoff.duration(), 1000);
});
it('reset() will reset the duration() value', function () {
const backoff = new ExponentialBackoff({min: 100, max: 1000})
assert.strictEqual(backoff.duration(), 100)
assert.strictEqual(backoff.duration(), 200)
assert.strictEqual(backoff.duration(), 400)
backoff.reset()
assert.strictEqual(backoff.duration(), 100)
assert.strictEqual(backoff.duration(), 200)
})
})
it("reset() will reset the duration() value", function () {
const backoff = new ExponentialBackoff({ min: 100, max: 1000 });
assert.strictEqual(backoff.duration(), 100);
assert.strictEqual(backoff.duration(), 200);
assert.strictEqual(backoff.duration(), 400);
backoff.reset();
assert.strictEqual(backoff.duration(), 100);
assert.strictEqual(backoff.duration(), 200);
});
});

View File

@@ -1,53 +1,52 @@
import _ from 'lodash'
import assert from 'assert-diff'
import setupClient from './setupClient'
import responses from './fixtures/responses'
import rippled from './fixtures/rippled'
import {ignoreWebSocketDisconnect} from './testUtils'
import assert from "assert-diff";
import _ from "lodash";
const TIMEOUT = 20000
import responses from "./fixtures/responses";
import rippled from "./fixtures/rippled";
import setupClient from "./setupClient";
import { ignoreWebSocketDisconnect } from "./testUtils";
const TIMEOUT = 20000;
function checkResult(expected, response) {
if (expected.txJSON) {
assert(response.txJSON)
assert.deepEqual(JSON.parse(response.txJSON), JSON.parse(expected.txJSON))
assert(response.txJSON);
assert.deepEqual(JSON.parse(response.txJSON), JSON.parse(expected.txJSON));
}
assert.deepEqual(_.omit(response, 'txJSON'), _.omit(expected, 'txJSON'))
return response
assert.deepEqual(_.omit(response, "txJSON"), _.omit(expected, "txJSON"));
return response;
}
describe('BroadcastClient', function () {
this.timeout(TIMEOUT)
beforeEach(setupClient.setupBroadcast)
afterEach(setupClient.teardown)
describe("BroadcastClient", function () {
this.timeout(TIMEOUT);
beforeEach(setupClient.setupBroadcast);
afterEach(setupClient.teardown);
it('base', function () {
it("base", function () {
this.mocks.forEach((mock) => {
mock.addResponse({command: 'server_info'}, rippled.server_info.normal)
})
assert(this.client.isConnected())
return this.client
.request({command: "server_info"})
.then(response => {
return checkResult(responses.getServerInfo, response.result.info)
})
})
mock.addResponse({ command: "server_info" }, rippled.server_info.normal);
});
assert(this.client.isConnected());
return this.client.request({ command: "server_info" }).then((response) => {
return checkResult(responses.getServerInfo, response.result.info);
});
});
it('error propagation', function (done) {
const data = {error: 'type', error_message: 'info'}
it("error propagation", function (done) {
const data = { error: "type", error_message: "info" };
this.mocks.forEach((mock) => {
mock.addResponse({command: 'echo'}, data)
})
this.client.once('error', (type, info) => {
assert.strictEqual(type, 'type')
assert.strictEqual(info, 'info')
done()
})
mock.addResponse({ command: "echo" }, data);
});
this.client.once("error", (type, info) => {
assert.strictEqual(type, "type");
assert.strictEqual(info, "info");
done();
});
this.client._clients[1].connection
.request({
command: 'echo',
data
command: "echo",
data,
})
.catch(ignoreWebSocketDisconnect)
})
})
.catch(ignoreWebSocketDisconnect);
});
});

View File

@@ -1,30 +1,35 @@
import assert from 'assert'
import puppeteer from 'puppeteer'
import { expect, assert } from "chai";
import puppeteer from "puppeteer";
describe("Browser Tests", () => {
it("Integration Tests", async () => {
const browser = await puppeteer.launch({"headless": true});
try {
const page = await browser.newPage().catch();
await page.goto(`file:///${__dirname}/../localIntegrationRunner.html`);
describe("Browser Tests", function () {
it("Integration Tests", async function () {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage().catch();
await page.goto(`file:///${__dirname}/../localIntegrationRunner.html`);
await page.waitForFunction('document.querySelector("body").innerText.includes("submit multisigned transaction")');
await page.waitForFunction(
'document.querySelector("body").innerText.includes("submit multisigned transaction")'
);
const fails = await page.evaluate(() => {
return document.querySelector('.failures').textContent
})
const passes = await page.evaluate(() => {
return document.querySelector('.passes').textContent
})
const fails = await page.evaluate(() => {
const element = document.querySelector(".failures");
assert.equal(fails, "failures: 0")
assert.notEqual(passes, "passes: 0")
return element == null ? null : element.textContent;
});
const passes = await page.evaluate(() => {
const element = document.querySelector(".passes");
} catch (err) {
console.log(err)
assert(false)
} finally {
await browser.close();
}
}).timeout(40000)
})
return element == null ? null : element.textContent;
});
expect(fails).to.equal("failures: 0");
expect(passes).to.not.equal("passes: 0");
} catch (err) {
console.log(err);
assert(false);
} finally {
await browser.close();
}
}).timeout(40000);
});

View File

@@ -1,10 +1,12 @@
import assert from 'assert-diff'
import binary from 'ripple-binary-codec'
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import {assertResultMatch, TestSuite} from '../testUtils'
const {combine: REQUEST_FIXTURES} = requests
const {combine: RESPONSE_FIXTURES} = responses
import assert from "assert-diff";
import binary from "ripple-binary-codec";
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import { assertResultMatch, TestSuite } from "../testUtils";
const { combine: REQUEST_FIXTURES } = requests;
const { combine: RESPONSE_FIXTURES } = responses;
/**
* Every test suite exports their tests in the default object.
@@ -12,18 +14,18 @@ const {combine: RESPONSE_FIXTURES} = responses
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'combine': async (client, address) => {
const combined = client.combine(REQUEST_FIXTURES.setDomain)
assertResultMatch(combined, RESPONSE_FIXTURES.single, 'sign')
async combine(client, address) {
const combined = client.combine(REQUEST_FIXTURES.setDomain);
assertResultMatch(combined, RESPONSE_FIXTURES.single, "sign");
},
'combine - different transactions': async (client, address) => {
const request = [REQUEST_FIXTURES.setDomain[0]]
const tx = binary.decode(REQUEST_FIXTURES.setDomain[0])
tx.Flags = 0
request.push(binary.encode(tx))
"combine - different transactions": async (client, address) => {
const request = [REQUEST_FIXTURES.setDomain[0]];
const tx = binary.decode(REQUEST_FIXTURES.setDomain[0]);
tx.Flags = 0;
request.push(binary.encode(tx));
assert.throws(() => {
client.combine(request)
}, /txJSON is not the same for all signedTransactions/)
}
}
client.combine(request);
}, /txJSON is not the same for all signedTransactions/);
},
};

View File

@@ -1,6 +1,8 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import {Client} from 'xrpl-local'
import assert from "assert-diff";
import { Client } from "xrpl-local";
import { TestSuite } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -8,22 +10,22 @@ import {Client} from 'xrpl-local'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'Client - implicit server port': () => {
new Client('wss://s1.ripple.com')
"Client - implicit server port": () => {
new Client("wss://s1.ripple.com");
},
'Client invalid options': () => {
// @ts-ignore - This is intentionally invalid
assert.throws(() => new Client({invalid: true}))
"Client invalid options": () => {
// @ts-expect-error - This is intentionally invalid
assert.throws(() => new Client({ invalid: true }));
},
'Client valid options': () => {
const client = new Client('wss://s:1')
const privateConnectionUrl = (client.connection as any)._url
assert.deepEqual(privateConnectionUrl, 'wss://s:1')
"Client valid options": () => {
const client = new Client("wss://s:1");
const privateConnectionUrl = (client.connection as any)._url;
assert.deepEqual(privateConnectionUrl, "wss://s:1");
},
'Client invalid server uri': () => {
assert.throws(() => new Client('wss//s:1'))
}
}
"Client invalid server uri": () => {
assert.throws(() => new Client("wss//s:1"));
},
};

View File

@@ -1,6 +1,7 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import {Client} from '../../src'
import assert from "assert-diff";
import { Client } from "../../src";
import { TestSuite } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -8,24 +9,24 @@ import {Client} from '../../src'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'returns address for public key': async (client, address) => {
"returns address for public key": async (client, address) => {
assert.equal(
Client.deriveXAddress({
publicKey:
'035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06',
"035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06",
tag: false,
test: false
test: false,
}),
'XVZVpQj8YSVpNyiwXYSqvQoQqgBttTxAZwMcuJd4xteQHyt'
)
"XVZVpQj8YSVpNyiwXYSqvQoQqgBttTxAZwMcuJd4xteQHyt"
);
assert.equal(
Client.deriveXAddress({
publicKey:
'035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06',
"035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06",
tag: false,
test: true
test: true,
}),
'TVVrSWtmQQssgVcmoMBcFQZKKf56QscyWLKnUyiuZW8ALU4'
)
}
}
"TVVrSWtmQQssgVcmoMBcFQZKKf56QscyWLKnUyiuZW8ALU4"
);
},
};

View File

@@ -1,5 +1,6 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import assert from "assert-diff";
import { TestSuite } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -7,13 +8,13 @@ import {TestSuite} from '../testUtils'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'RippleError with data': async (client, address) => {
const error = new client.errors.RippleError('_message_', '_data_')
assert.strictEqual(error.toString(), "[RippleError(_message_, '_data_')]")
"RippleError with data": async (client, address) => {
const error = new client.errors.RippleError("_message_", "_data_");
assert.strictEqual(error.toString(), "[RippleError(_message_, '_data_')]");
},
'NotFoundError default message': async (client, address) => {
const error = new client.errors.NotFoundError()
assert.strictEqual(error.toString(), '[NotFoundError(Not found)]')
}
}
"NotFoundError default message": async (client, address) => {
const error = new client.errors.NotFoundError();
assert.strictEqual(error.toString(), "[NotFoundError(Not found)]");
},
};

View File

@@ -3,7 +3,7 @@
// import {Client} from 'xrpl-local'
// import requests from '../fixtures/requests'
// import responses from '../fixtures/responses'
import {TestSuite} from '../testUtils'
import { TestSuite } from "../testUtils";
// function checkSortingOfOrders(orders) {
// let previousRate = '0'
@@ -56,7 +56,6 @@ export default <TestSuite>{
// counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
// }
// }
// await Promise.all([
// client.request({command: 'book_offers',
// taker_gets: orderbookInfo.base,
@@ -88,7 +87,6 @@ export default <TestSuite>{
// assert.deepEqual(orderbook, responses.getOrderbook.normal)
// })
// },
// 'with XRP': async (client, address) => {
// const orderbookInfo = {
// base: {
@@ -99,7 +97,6 @@ export default <TestSuite>{
// currency: 'XRP'
// }
// }
// await Promise.all([
// client.request({command: 'book_offers',
// taker_gets: orderbookInfo.base,
@@ -131,7 +128,6 @@ export default <TestSuite>{
// assert.deepEqual(orderbook, responses.getOrderbook.withXRP)
// })
// },
// 'sample XRP/JPY book has orders sorted correctly': async (client, address) => {
// const orderbookInfo = {
// base: {
@@ -143,9 +139,7 @@ export default <TestSuite>{
// issuer: 'rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS'
// }
// }
// const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR'
// await Promise.all([
// client.request({command: 'book_offers',
// taker_gets: orderbookInfo.base,
@@ -178,7 +172,6 @@ export default <TestSuite>{
// return checkSortingOfOrders(orderbook.asks)
// })
// },
// 'sample USD/XRP book has orders sorted correctly': async (client, address) => {
// const orderbookInfo = {
// counter: {currency: 'XRP'},
@@ -187,9 +180,7 @@ export default <TestSuite>{
// counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
// }
// }
// const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR'
// await Promise.all([
// client.request({command: 'book_offers',
// taker_gets: orderbookInfo.base,
@@ -224,7 +215,6 @@ export default <TestSuite>{
// )
// })
// },
// 'sorted so that best deals come first': async (client, address) => {
// const orderbookInfo = {
// base: {
@@ -236,7 +226,6 @@ export default <TestSuite>{
// counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
// }
// }
// await Promise.all([
// client.request({command: 'book_offers',
// taker_gets: orderbookInfo.base,
@@ -265,7 +254,6 @@ export default <TestSuite>{
// ...directOffers,
// ...reverseOffers
// ])
// const bidRates = orderbook.bids.map(
// (bid) => bid.properties.makerExchangeRate
// )
@@ -279,7 +267,6 @@ export default <TestSuite>{
// assert.deepEqual(askRates.map((x) => Number(x)).sort(), askRates)
// })
// },
// 'currency & counterparty are correct': async (client, address) => {
// const orderbookInfo = {
// base: {
@@ -291,7 +278,6 @@ export default <TestSuite>{
// counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
// }
// }
// await Promise.all([
// client.request({command: 'book_offers',
// taker_gets: orderbookInfo.base,
@@ -320,7 +306,6 @@ export default <TestSuite>{
// ...directOffers,
// ...reverseOffers
// ])
// const orders = [...orderbook.bids, ...orderbook.asks]
// orders.forEach((order) => {
// const quantity = order.specification.quantity
@@ -333,7 +318,6 @@ export default <TestSuite>{
// })
// })
// },
// 'direction is correct for bids and asks': async (client, address) => {
// const orderbookInfo = {
// base: {
@@ -345,7 +329,6 @@ export default <TestSuite>{
// counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
// }
// }
// await Promise.all([
// client.request({command: 'book_offers',
// taker_gets: orderbookInfo.base,
@@ -374,7 +357,6 @@ export default <TestSuite>{
// ...directOffers,
// ...reverseOffers
// ])
// assert(
// orderbook.bids.every((bid) => bid.specification.direction === 'buy')
// )
@@ -383,4 +365,4 @@ export default <TestSuite>{
// )
// })
// }
}
};

View File

@@ -1,7 +1,7 @@
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import rippledAccountLines from '../fixtures/rippled/accountLines'
import {assertResultMatch, TestSuite} from '../testUtils'
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import rippledAccountLines from "../fixtures/rippled/accountLines";
import { assertResultMatch, TestSuite } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -9,54 +9,82 @@ import {assertResultMatch, TestSuite} from '../testUtils'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'getBalances': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal)
mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal)
const result = await client.getBalances(address)
assertResultMatch(result, responses.getBalances, 'getBalances')
async getBalances(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
mockRippled.addResponse(
{ command: "account_lines" },
rippledAccountLines.normal
);
mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal);
const result = await client.getBalances(address);
assertResultMatch(result, responses.getBalances, "getBalances");
},
'getBalances - limit': async (client, address, mockRippled) => {
const options = {limit: 3, ledgerVersion: 123456}
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal)
mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal)
const expectedResponse = responses.getBalances.slice(0, 3)
const result = await client.getBalances(address, options)
assertResultMatch(result, expectedResponse, 'getBalances')
"getBalances - limit": async (client, address, mockRippled) => {
const options = { limit: 3, ledgerVersion: 123456 };
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
mockRippled.addResponse(
{ command: "account_lines" },
rippledAccountLines.normal
);
mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal);
const expectedResponse = responses.getBalances.slice(0, 3);
const result = await client.getBalances(address, options);
assertResultMatch(result, expectedResponse, "getBalances");
},
'getBalances - limit & currency': async (client, address, mockRippled) => {
const options = {currency: 'USD', limit: 3}
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal)
mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal)
"getBalances - limit & currency": async (client, address, mockRippled) => {
const options = { currency: "USD", limit: 3 };
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
mockRippled.addResponse(
{ command: "account_lines" },
rippledAccountLines.normal
);
mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal);
const expectedResponse = responses.getBalances
.filter((item) => item.currency === 'USD')
.slice(0, 3)
const result = await client.getBalances(address, options)
assertResultMatch(result, expectedResponse, 'getBalances')
.filter((item) => item.currency === "USD")
.slice(0, 3);
const result = await client.getBalances(address, options);
assertResultMatch(result, expectedResponse, "getBalances");
},
'getBalances - limit & currency & issuer': async (client, address, mockRippled) => {
"getBalances - limit & currency & issuer": async (
client,
address,
mockRippled
) => {
const options = {
currency: 'USD',
counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
limit: 3
}
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal)
mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal)
currency: "USD",
counterparty: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
limit: 3,
};
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
mockRippled.addResponse(
{ command: "account_lines" },
rippledAccountLines.normal
);
mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal);
const expectedResponse = responses.getBalances
.filter(
(item) =>
item.currency === 'USD' &&
item.counterparty === 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
item.currency === "USD" &&
item.counterparty === "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
)
.slice(0, 3)
const result = await client.getBalances(address, options)
assertResultMatch(result, expectedResponse, 'getBalances')
}
}
.slice(0, 3);
const result = await client.getBalances(address, options);
assertResultMatch(result, expectedResponse, "getBalances");
},
};

View File

@@ -1,6 +1,7 @@
import assert from 'assert-diff'
import rippled from '../fixtures/rippled'
import {TestSuite} from '../testUtils'
import assert from "assert-diff";
import rippled from "../fixtures/rippled";
import { TestSuite } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -8,54 +9,78 @@ import {TestSuite} from '../testUtils'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'getFee': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
const fee = await client.getFee()
assert.strictEqual(fee, '0.000012')
async getFee(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
const fee = await client.getFee();
assert.strictEqual(fee, "0.000012");
},
'getFee default': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
client._feeCushion = undefined
const fee = await client.getFee()
assert.strictEqual(fee, '0.000012')
"getFee default": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
client._feeCushion = undefined as unknown as number;
const fee = await client.getFee();
assert.strictEqual(fee, "0.000012");
},
'getFee - high load_factor': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.highLoadFactor)
const fee = await client.getFee()
assert.strictEqual(fee, '2')
"getFee - high load_factor": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.highLoadFactor
);
const fee = await client.getFee();
assert.strictEqual(fee, "2");
},
'getFee - high load_factor with custom maxFeeXRP': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.highLoadFactor)
"getFee - high load_factor with custom maxFeeXRP": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.highLoadFactor
);
// Ensure that overriding with high maxFeeXRP of '51540' causes no errors.
// (fee will actually be 51539.607552)
client._maxFeeXRP = '51540'
const fee = await client.getFee()
assert.strictEqual(fee, '51539.607552')
client._maxFeeXRP = "51540";
const fee = await client.getFee();
assert.strictEqual(fee, "51539.607552");
},
'getFee custom cushion': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
client._feeCushion = 1.4
const fee = await client.getFee()
assert.strictEqual(fee, '0.000014')
"getFee custom cushion": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
client._feeCushion = 1.4;
const fee = await client.getFee();
assert.strictEqual(fee, "0.000014");
},
// This is not recommended since it may result in attempting to pay
// less than the base fee. However, this test verifies the existing behavior.
'getFee cushion less than 1.0': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
client._feeCushion = 0.9
const fee = await client.getFee()
assert.strictEqual(fee, '0.000009')
"getFee cushion less than 1.0": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
client._feeCushion = 0.9;
const fee = await client.getFee();
assert.strictEqual(fee, "0.000009");
},
'getFee reporting': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
const fee = await client.getFee()
assert.strictEqual(fee, '0.000012')
}
}
"getFee reporting": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
const fee = await client.getFee();
assert.strictEqual(fee, "0.000012");
},
};

View File

@@ -1,9 +1,10 @@
import assert from 'assert-diff'
import responses from '../fixtures/responses'
import requests from '../fixtures/requests'
import rippled from '../fixtures/rippled'
import {TestSuite, assertResultMatch, assertRejects} from '../testUtils'
import { BookOffersRequest } from '../../src'
import assert from "assert-diff";
import { BookOffersRequest } from "../../src";
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { TestSuite, assertResultMatch, assertRejects } from "../testUtils";
// import BigNumber from 'bignumber.js'
// function checkSortingOfOrders(orders) {
@@ -41,11 +42,17 @@ import { BookOffersRequest } from '../../src'
// }
function isUSD(currency: string) {
return currency === 'USD' || currency === '0000000000000000000000005553440000000000'
return (
currency === "USD" ||
currency === "0000000000000000000000005553440000000000"
);
}
function isBTC(currency: string) {
return currency === 'BTC' || currency === '0000000000000000000000004254430000000000'
return (
currency === "BTC" ||
currency === "0000000000000000000000004254430000000000"
);
}
function normalRippledResponse(request: BookOffersRequest): object {
@@ -53,23 +60,27 @@ function normalRippledResponse(request: BookOffersRequest): object {
isBTC(request.taker_gets.currency) &&
isUSD(request.taker_pays.currency)
) {
return rippled.book_offers.fabric.requestBookOffersBidsResponse(request)
} else if (
return rippled.book_offers.fabric.requestBookOffersBidsResponse(request);
}
if (
isUSD(request.taker_gets.currency) &&
isBTC(request.taker_pays.currency)
) {
return rippled.book_offers.fabric.requestBookOffersAsksResponse(request)
return rippled.book_offers.fabric.requestBookOffersAsksResponse(request);
}
return {};
}
function xrpRippledResponse(request: BookOffersRequest): object {
if (request.taker_pays.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw') {
return rippled.book_offers.xrp_usd
} else if (
request.taker_gets.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw'
) {
return rippled.book_offers.usd_xrp
if (request.taker_pays.issuer === "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw") {
return rippled.book_offers.xrp_usd;
}
if (request.taker_gets.issuer === "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw") {
return rippled.book_offers.usd_xrp;
}
return {};
}
/**
@@ -78,34 +89,34 @@ function xrpRippledResponse(request: BookOffersRequest): object {
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'normal': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse)
async normal(client, address, mockRippled) {
mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse);
const response = await client.getOrderbook(
address,
requests.getOrderbook.normal,
{limit: 20}
)
assertResultMatch(response, responses.getOrderbook.normal, 'getOrderbook')
{ limit: 20 }
);
assertResultMatch(response, responses.getOrderbook.normal, "getOrderbook");
},
'invalid options': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse)
"invalid options": async (client, address, mockRippled) => {
mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse);
assertRejects(
client.getOrderbook(address, requests.getOrderbook.normal, {
// @ts-ignore
invalid: 'options'
// @ts-expect-error
invalid: "options",
}),
client.errors.ValidationError
)
);
},
'with XRP': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'book_offers'}, xrpRippledResponse)
"with XRP": async (client, address, mockRippled) => {
mockRippled.addResponse({ command: "book_offers" }, xrpRippledResponse);
const response = await client.getOrderbook(
address,
requests.getOrderbook.withXRP
)
assertResultMatch(response, responses.getOrderbook.withXRP, 'getOrderbook')
);
assertResultMatch(response, responses.getOrderbook.withXRP, "getOrderbook");
},
// 'sample XRP/JPY book has orders sorted correctly': async (client, address, mockRippled) => {
@@ -140,55 +151,69 @@ export default <TestSuite>{
// },
// WARNING: This test fails to catch the sorting bug, issue #766
'sorted so that best deals come first [bad test]': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse)
"sorted so that best deals come first [bad test]": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse);
const response = await client.getOrderbook(
address,
requests.getOrderbook.normal
)
);
const bidRates = response.bids.map(
(bid) => bid.properties.makerExchangeRate
)
);
const askRates = response.asks.map(
(ask) => ask.properties.makerExchangeRate
)
);
// makerExchangeRate = quality = takerPays.value/takerGets.value
// so the best deal for the taker is the lowest makerExchangeRate
// bids and asks should be sorted so that the best deals come first
assert.deepEqual(
bidRates.sort((x) => Number(x)),
bidRates
)
);
assert.deepEqual(
askRates.sort((x) => Number(x)),
askRates
)
);
},
'currency & counterparty are correct': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse)
"currency & counterparty are correct": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse);
const response = await client.getOrderbook(
address,
requests.getOrderbook.normal
)
;[...response.bids, ...response.asks].forEach((order) => {
const quantity = order.specification.quantity
const totalPrice = order.specification.totalPrice
const {base, counter} = requests.getOrderbook.normal
assert.strictEqual(quantity.currency, base.currency)
assert.strictEqual(quantity.counterparty, base.counterparty)
assert.strictEqual(totalPrice.currency, counter.currency)
assert.strictEqual(totalPrice.counterparty, counter.counterparty)
})
);
[...response.bids, ...response.asks].forEach((order) => {
const quantity = order.specification.quantity;
const totalPrice = order.specification.totalPrice;
const { base, counter } = requests.getOrderbook.normal;
assert.strictEqual(quantity.currency, base.currency);
assert.strictEqual(quantity.counterparty, base.counterparty);
assert.strictEqual(totalPrice.currency, counter.currency);
assert.strictEqual(totalPrice.counterparty, counter.counterparty);
});
},
'direction is correct for bids and asks': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse)
"direction is correct for bids and asks": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse);
const response = await client.getOrderbook(
address,
requests.getOrderbook.normal
)
assert(response.bids.every((bid) => bid.specification.direction === 'buy'))
assert(response.asks.every((ask) => ask.specification.direction === 'sell'))
}
}
);
assert(response.bids.every((bid) => bid.specification.direction === "buy"));
assert(
response.asks.every((ask) => ask.specification.direction === "sell")
);
},
};

View File

@@ -1,10 +1,11 @@
import assert from 'assert-diff'
import { assertRejects, TestSuite } from '../testUtils'
import requests from '../fixtures/requests'
import assert from "assert-diff";
import addresses from "../fixtures/addresses.json";
import requests from "../fixtures/requests";
import rippled from "../fixtures/rippled";
import { assertRejects, TestSuite } from "../testUtils";
// import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import addresses from '../fixtures/addresses.json'
const {getPaths: REQUEST_FIXTURES} = requests
const { getPaths: REQUEST_FIXTURES } = requests;
// const {getPaths: RESPONSE_FIXTURES} = responses
const rippledResponse = rippled.path_find.generate.generateIOUPaymentPaths(
@@ -12,7 +13,7 @@ const rippledResponse = rippled.path_find.generate.generateIOUPaymentPaths(
REQUEST_FIXTURES.normal.source.address,
REQUEST_FIXTURES.normal.destination.address,
REQUEST_FIXTURES.normal.destination.amount
)
);
/**
* Every test suite exports their tests in the default object.
@@ -46,12 +47,12 @@ export default <TestSuite>{
// const response = await client.getPaths(REQUEST_FIXTURES.XrpToXrp)
// assertResultMatch(response, RESPONSE_FIXTURES.XrpToXrp, 'getPaths')
// },
'source with issuer': async (client, _, mockRippled) => {
mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse)
"source with issuer": async (client, _, mockRippled) => {
mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse);
return assertRejects(
client.getPaths(REQUEST_FIXTURES.issuer),
client.errors.NotFoundError
)
);
},
// 'XRP 2 XRP - not enough': async (client) => {
// return assertRejects(
@@ -59,52 +60,52 @@ export default <TestSuite>{
// client.errors.NotFoundError
// )
// },
'invalid PathFind': async (client, _, mockRippled) => {
mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse)
"invalid PathFind": async (client, _, mockRippled) => {
mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse);
assert.throws(() => {
client.getPaths(REQUEST_FIXTURES.invalid)
}, /Cannot specify both source.amount/)
client.getPaths(REQUEST_FIXTURES.invalid);
}, /Cannot specify both source.amount/);
},
'does not accept currency': async (client, _, mockRippled) => {
mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse)
"does not accept currency": async (client, _, mockRippled) => {
mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse);
return assertRejects(
client.getPaths(REQUEST_FIXTURES.NotAcceptCurrency),
client.errors.NotFoundError
)
);
},
'no paths': async (client, _, mockRippled) => {
mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse)
"no paths": async (client, _, mockRippled) => {
mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse);
return assertRejects(
client.getPaths(REQUEST_FIXTURES.NoPaths),
client.errors.NotFoundError
)
);
},
'no paths source amount': async (client, _, mockRippled) => {
mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse)
"no paths source amount": async (client, _, mockRippled) => {
mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse);
return assertRejects(
client.getPaths(REQUEST_FIXTURES.NoPathsSource),
client.errors.NotFoundError
)
);
},
'no paths with source currencies': async (client, _, mockRippled) => {
mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse)
"no paths with source currencies": async (client, _, mockRippled) => {
mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse);
return assertRejects(
client.getPaths(REQUEST_FIXTURES.NoPathsWithCurrencies),
client.errors.NotFoundError
)
);
},
'error: srcActNotFound': async (client, _, mockRippled) => {
mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse)
"error: srcActNotFound": async (client, _, mockRippled) => {
mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse);
return assertRejects(
client.getPaths({
...REQUEST_FIXTURES.normal,
source: {address: addresses.NOTFOUND}
source: { address: addresses.NOTFOUND },
}),
client.errors.RippleError
)
);
},
// 'send all': async (client) => {
// const response = await client.getPaths(REQUEST_FIXTURES.sendAll)
// assertResultMatch(response, RESPONSE_FIXTURES.sendAll, 'getPaths')
// }
}
};

View File

@@ -1,8 +1,9 @@
import addresses from '../fixtures/addresses.json'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled/accountLines'
import {assertResultMatch, TestSuite} from '../testUtils'
const {getTrustlines: RESPONSE_FIXTURES} = responses
import addresses from "../fixtures/addresses.json";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled/accountLines";
import { assertResultMatch, TestSuite } from "../testUtils";
const { getTrustlines: RESPONSE_FIXTURES } = responses;
/**
* Every test suite exports their tests in the default object.
@@ -10,46 +11,63 @@ const {getTrustlines: RESPONSE_FIXTURES} = responses
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'getTrustlines - filtered': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_lines'}, rippled.normal)
const options = {currency: 'USD'}
const result = await client.getTrustlines(address, options)
assertResultMatch(result, RESPONSE_FIXTURES.filtered, 'getTrustlines')
"getTrustlines - filtered": async (client, address, mockRippled) => {
mockRippled.addResponse({ command: "account_lines" }, rippled.normal);
const options = { currency: "USD" };
const result = await client.getTrustlines(address, options);
assertResultMatch(result, RESPONSE_FIXTURES.filtered, "getTrustlines");
},
'getTrustlines - more than 400 items': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_lines'}, rippled.manyItems)
const options = {limit: 401}
const result = await client.getTrustlines(address, options)
"getTrustlines - more than 400 items": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({ command: "account_lines" }, rippled.manyItems);
const options = { limit: 401 };
const result = await client.getTrustlines(address, options);
assertResultMatch(
result,
RESPONSE_FIXTURES.moreThan400Items,
'getTrustlines'
)
"getTrustlines"
);
},
'getTrustlines - no options': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_lines'}, rippled.normal)
await client.getTrustlines(address)
"getTrustlines - no options": async (client, address, mockRippled) => {
mockRippled.addResponse({ command: "account_lines" }, rippled.normal);
await client.getTrustlines(address);
},
'getTrustlines - ripplingDisabled works properly': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_lines'}, rippled.ripplingDisabled)
const result = await client.getTrustlines(address)
"getTrustlines - ripplingDisabled works properly": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "account_lines" },
rippled.ripplingDisabled
);
const result = await client.getTrustlines(address);
assertResultMatch(
result,
RESPONSE_FIXTURES.ripplingDisabled,
'getTrustlines'
)
"getTrustlines"
);
},
'getTrustlines - ledger version option': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_lines'}, rippled.manyItems)
const result = await client.getTrustlines(addresses.FOURTH_ACCOUNT, {ledgerVersion: 5})
"getTrustlines - ledger version option": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({ command: "account_lines" }, rippled.manyItems);
const result = await client.getTrustlines(addresses.FOURTH_ACCOUNT, {
ledgerVersion: 5,
});
assertResultMatch(
result,
RESPONSE_FIXTURES.moreThan400Items,
'getTrustlines'
)
"getTrustlines"
);
},
}
};

View File

@@ -1,6 +1,7 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import rippled from '../fixtures/rippled'
import assert from "assert-diff";
import rippled from "../fixtures/rippled";
import { TestSuite } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -8,29 +9,36 @@ import rippled from '../fixtures/rippled'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'returns true when there is another page': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'ledger_data'}, rippled.ledger_data.first_page)
// @ts-ignore
const response = await client.request({command: 'ledger_data'})
assert(client.hasNextPage(response))
"returns true when there is another page": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "ledger_data" },
rippled.ledger_data.first_page
);
const response = await client.request({ command: "ledger_data" });
assert(client.hasNextPage(response));
},
'returns false when there are no more pages': async (client, address, mockRippled) => {
const rippledResponse = function(request: Request) : object {
if ('marker' in request) {
return rippled.ledger_data.last_page
} else {
return rippled.ledger_data.first_page
"returns false when there are no more pages": async (
client,
address,
mockRippled
) => {
const rippledResponse = function (request: Request): object {
if ("marker" in request) {
return rippled.ledger_data.last_page;
}
}
mockRippled.addResponse({command: 'ledger_data'}, rippledResponse)
// @ts-ignore
const response = await client.request({command: 'ledger_data'})
return rippled.ledger_data.first_page;
};
mockRippled.addResponse({ command: "ledger_data" }, rippledResponse);
const response = await client.request({ command: "ledger_data" });
const responseNextPage = await client.requestNextPage(
// @ts-ignore
{command: 'ledger_data'},
{ command: "ledger_data" },
response
)
assert(!client.hasNextPage(responseNextPage))
}
}
);
assert(!client.hasNextPage(responseNextPage));
},
};

View File

@@ -1,5 +1,6 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import assert from "assert-diff";
import { TestSuite } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -7,9 +8,9 @@ import {TestSuite} from '../testUtils'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'disconnect & isConnected': async (client, address) => {
assert.strictEqual(client.isConnected(), true)
await client.disconnect()
assert.strictEqual(client.isConnected(), false)
}
}
"disconnect & isConnected": async (client, address) => {
assert.strictEqual(client.isConnected(), true);
await client.disconnect();
assert.strictEqual(client.isConnected(), false);
},
};

View File

@@ -1,17 +1,18 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import addresses from '../fixtures/addresses.json'
import assert from "assert-diff";
import addresses from "../fixtures/addresses.json";
import { TestSuite } from "../testUtils";
export default <TestSuite>{
'returns true for valid address': async (client, address) => {
assert(client.isValidAddress('rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K'))
assert(client.isValidAddress(addresses.ACCOUNT_X))
assert(client.isValidAddress(addresses.ACCOUNT_T))
"returns true for valid address": async (client, address) => {
assert(client.isValidAddress("rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K"));
assert(client.isValidAddress(addresses.ACCOUNT_X));
assert(client.isValidAddress(addresses.ACCOUNT_T));
},
'returns false for invalid address': async (client, address) => {
assert(!client.isValidAddress('foobar'))
assert(!client.isValidAddress(addresses.ACCOUNT_X.slice(0, -1)))
assert(!client.isValidAddress(addresses.ACCOUNT_T.slice(1)))
}
}
"returns false for invalid address": async (client, address) => {
assert(!client.isValidAddress("foobar"));
assert(!client.isValidAddress(addresses.ACCOUNT_X.slice(0, -1)));
assert(!client.isValidAddress(addresses.ACCOUNT_T.slice(1)));
},
};

View File

@@ -1,12 +1,13 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import assert from "assert-diff";
import { TestSuite } from "../testUtils";
export default <TestSuite>{
'returns true for valid secret': async (client, address) => {
assert(client.isValidSecret('snsakdSrZSLkYpCXxfRkS4Sh96PMK'))
"returns true for valid secret": async (client, address) => {
assert(client.isValidSecret("snsakdSrZSLkYpCXxfRkS4Sh96PMK"));
},
'returns false for invalid secret': async (client, address) => {
assert(!client.isValidSecret('foobar'))
}
}
"returns false for invalid secret": async (client, address) => {
assert(!client.isValidSecret("foobar"));
},
};

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,33 +11,51 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'prepareCheckCancel': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async prepareCheckCancel(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareCheckCancel(
address,
requests.prepareCheckCancel.normal
)
assertResultMatch(result, responses.prepareCheckCancel.normal, 'prepare')
);
assertResultMatch(result, responses.prepareCheckCancel.normal, "prepare");
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.prepareCheckCancel(
address,
requests.prepareCheckCancel.normal,
localInstructions
)
assertResultMatch(result, responses.prepareCheckCancel.ticket, 'prepare')
}
}
);
assertResultMatch(result, responses.prepareCheckCancel.ticket, "prepare");
},
};

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,45 +11,72 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'prepareCheckCash amount': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareCheckCash amount": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareCheckCash(
address,
requests.prepareCheckCash.amount
)
assertResultMatch(result, responses.prepareCheckCash.amount, 'prepare')
);
assertResultMatch(result, responses.prepareCheckCash.amount, "prepare");
},
'prepareCheckCash deliverMin': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareCheckCash deliverMin": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareCheckCash(
address,
requests.prepareCheckCash.deliverMin
)
assertResultMatch(result, responses.prepareCheckCash.deliverMin, 'prepare')
);
assertResultMatch(result, responses.prepareCheckCash.deliverMin, "prepare");
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.prepareCheckCash(
address,
requests.prepareCheckCash.amount,
localInstructions
)
assertResultMatch(result, responses.prepareCheckCash.ticket, 'prepare')
}
}
);
assertResultMatch(result, responses.prepareCheckCash.ticket, "prepare");
},
};

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,50 +11,77 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'prepareCheckCreate': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async prepareCheckCreate(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012'
}
maxFee: "0.000012",
};
const result = await client.prepareCheckCreate(
address,
requests.prepareCheckCreate.normal,
localInstructions
)
assertResultMatch(result, responses.prepareCheckCreate.normal, 'prepare')
);
assertResultMatch(result, responses.prepareCheckCreate.normal, "prepare");
},
'prepareCheckCreate full': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareCheckCreate full": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareCheckCreate(
address,
requests.prepareCheckCreate.full
)
assertResultMatch(result, responses.prepareCheckCreate.full, 'prepare')
);
assertResultMatch(result, responses.prepareCheckCreate.full, "prepare");
},
'prepareCheckCreate with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareCheckCreate with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.prepareCheckCreate(
address,
requests.prepareCheckCreate.normal,
localInstructions
)
assertResultMatch(result, responses.prepareCheckCreate.ticket, 'prepare')
}
}
);
assertResultMatch(result, responses.prepareCheckCreate.ticket, "prepare");
},
};

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,58 +11,89 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'prepareEscrowCancellation': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async prepareEscrowCancellation(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareEscrowCancellation(
address,
requests.prepareEscrowCancellation.normal,
instructionsWithMaxLedgerVersionOffset
)
);
assertResultMatch(
result,
responses.prepareEscrowCancellation.normal,
'prepare'
)
"prepare"
);
},
'prepareEscrowCancellation with memos': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareEscrowCancellation with memos": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareEscrowCancellation(
address,
requests.prepareEscrowCancellation.memos
)
);
assertResultMatch(
result,
responses.prepareEscrowCancellation.memos,
'prepare'
)
"prepare"
);
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.prepareEscrowCancellation(
address,
requests.prepareEscrowCancellation.normal,
localInstructions
)
);
assertResultMatch(
result,
responses.prepareEscrowCancellation.ticket,
'prepare'
)
}
}
"prepare"
);
},
};

View File

@@ -1,15 +1,16 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertRejects, assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertRejects, assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
export const config = {
// TODO: The mock server right now returns a hard-coded string, no matter
// what "Account" value you pass. We'll need it to support more accurate
// responses before we can turn these tests on.
skipXAddress: true
}
skipXAddress: true,
};
/**
* Every test suite exports their tests in the default object.
@@ -17,64 +18,108 @@ export const config = {
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'prepareEscrowCreation': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async prepareEscrowCreation(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012'
}
maxFee: "0.000012",
};
const result = await client.prepareEscrowCreation(
address,
requests.prepareEscrowCreation.normal,
localInstructions
)
assertResultMatch(result, responses.prepareEscrowCreation.normal, 'prepare')
);
assertResultMatch(
result,
responses.prepareEscrowCreation.normal,
"prepare"
);
},
'prepareEscrowCreation full': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareEscrowCreation full": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareEscrowCreation(
address,
requests.prepareEscrowCreation.full
)
assertResultMatch(result, responses.prepareEscrowCreation.full, 'prepare')
);
assertResultMatch(result, responses.prepareEscrowCreation.full, "prepare");
},
'prepareEscrowCreation - invalid': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const escrow = Object.assign({}, requests.prepareEscrowCreation.full)
delete escrow.amount // Make invalid
"prepareEscrowCreation - invalid": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const escrow = { ...requests.prepareEscrowCreation.full };
delete escrow.amount; // Make invalid
await assertRejects(
client.prepareEscrowCreation(address, escrow),
client.errors.ValidationError,
'instance.escrowCreation requires property "amount"'
)
);
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000396',
ticketSequence: 23
}
maxFee: "0.000396",
ticketSequence: 23,
};
const result = await client.prepareEscrowCreation(
address,
requests.prepareEscrowCreation.normal,
localInstructions
)
assertResultMatch(result, responses.prepareEscrowCreation.ticket, 'prepare')
}
}
);
assertResultMatch(
result,
responses.prepareEscrowCreation.ticket,
"prepare"
);
},
};

View File

@@ -1,8 +1,9 @@
import {TestSuite, assertRejects, assertResultMatch} from '../testUtils'
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { TestSuite, assertRejects, assertResultMatch } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,44 +11,75 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'prepareEscrowExecution': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async prepareEscrowExecution(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareEscrowExecution(
address,
requests.prepareEscrowExecution.normal,
instructionsWithMaxLedgerVersionOffset
)
);
assertResultMatch(
result,
responses.prepareEscrowExecution.normal,
'prepare'
)
"prepare"
);
},
'prepareEscrowExecution - simple': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareEscrowExecution - simple": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareEscrowExecution(
address,
requests.prepareEscrowExecution.simple
)
);
assertResultMatch(
result,
responses.prepareEscrowExecution.simple,
'prepare'
)
"prepare"
);
},
'prepareEscrowExecution - no condition': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareEscrowExecution - no condition": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
await assertRejects(
client.prepareEscrowExecution(
address,
@@ -56,14 +88,27 @@ export default <TestSuite>{
),
client.errors.ValidationError,
'"condition" and "fulfillment" fields on EscrowFinish must only be specified together.'
)
);
},
'prepareEscrowExecution - no fulfillment': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepareEscrowExecution - no fulfillment": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
await assertRejects(
client.prepareEscrowExecution(
address,
@@ -72,28 +117,37 @@ export default <TestSuite>{
),
client.errors.ValidationError,
'"condition" and "fulfillment" fields on EscrowFinish must only be specified together.'
)
);
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000396',
ticketSequence: 23
}
maxFee: "0.000396",
ticketSequence: 23,
};
const result = await client.prepareEscrowExecution(
address,
requests.prepareEscrowExecution.normal,
localInstructions
)
);
assertResultMatch(
result,
responses.prepareEscrowExecution.ticket,
'prepare'
)
}
}
"prepare"
);
},
};

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertRejects, assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertRejects, assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,52 +11,88 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'buy order': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrder.buy
const result = await client.prepareOrder(address, request)
assertResultMatch(result, responses.prepareOrder.buy, 'prepare')
"buy order": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrder.buy;
const result = await client.prepareOrder(address, request);
assertResultMatch(result, responses.prepareOrder.buy, "prepare");
},
'buy order with expiration': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrder.expiration
const response = responses.prepareOrder.expiration
"buy order with expiration": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrder.expiration;
const response = responses.prepareOrder.expiration;
const result = await client.prepareOrder(
address,
request,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(result, response, 'prepare')
);
assertResultMatch(result, response, "prepare");
},
'sell order': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrder.sell
"sell order": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrder.sell;
const result = await client.prepareOrder(
address,
request,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(result, responses.prepareOrder.sell, 'prepare')
);
assertResultMatch(result, responses.prepareOrder.sell, "prepare");
},
'invalid': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = Object.assign({}, requests.prepareOrder.sell)
delete request.direction // Make invalid
async invalid(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = { ...requests.prepareOrder.sell };
delete request.direction; // Make invalid
await assertRejects(
client.prepareOrder(
address,
@@ -64,21 +101,34 @@ export default <TestSuite>{
),
client.errors.ValidationError,
'instance.order requires property "direction"'
)
);
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrder.sell
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrder.sell;
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
const result = await client.prepareOrder(address, request, localInstructions)
assertResultMatch(result, responses.prepareOrder.ticket, 'prepare')
}
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.prepareOrder(
address,
request,
localInstructions
);
assertResultMatch(result, responses.prepareOrder.ticket, "prepare");
},
};

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertRejects, assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertRejects, assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,90 +11,134 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'prepareOrderCancellation': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrderCancellation.simple
async prepareOrderCancellation(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrderCancellation.simple;
const result = await client.prepareOrderCancellation(
address,
request,
instructionsWithMaxLedgerVersionOffset
)
);
assertResultMatch(
result,
responses.prepareOrderCancellation.normal,
'prepare'
)
"prepare"
);
},
'no instructions': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrderCancellation.simple
const result = await client.prepareOrderCancellation(address, request)
"no instructions": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrderCancellation.simple;
const result = await client.prepareOrderCancellation(address, request);
assertResultMatch(
result,
responses.prepareOrderCancellation.noInstructions,
'prepare'
)
"prepare"
);
},
'with memos': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrderCancellation.withMemos
const result = await client.prepareOrderCancellation(address, request)
"with memos": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrderCancellation.withMemos;
const result = await client.prepareOrderCancellation(address, request);
assertResultMatch(
result,
responses.prepareOrderCancellation.withMemos,
'prepare'
)
"prepare"
);
},
'invalid': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = Object.assign(
{},
requests.prepareOrderCancellation.withMemos
)
delete request.orderSequence // Make invalid
async invalid(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = {
...requests.prepareOrderCancellation.withMemos,
};
delete request.orderSequence; // Make invalid
await assertRejects(
client.prepareOrderCancellation(address, request),
client.errors.ValidationError,
'instance.orderCancellation requires property "orderSequence"'
)
);
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const request = requests.prepareOrderCancellation.simple
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const request = requests.prepareOrderCancellation.simple;
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.prepareOrderCancellation(
address,
request,
localInstructions
)
);
assertResultMatch(
result,
responses.prepareOrderCancellation.ticket,
'prepare'
)
}
}
"prepare"
);
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,13 @@
import assert from 'assert-diff'
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
const {preparePaymentChannelClaim: REQUEST_FIXTURES} = requests
const {preparePaymentChannelClaim: RESPONSE_FIXTURES} = responses
import assert from "assert-diff";
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
const { preparePaymentChannelClaim: REQUEST_FIXTURES } = requests;
const { preparePaymentChannelClaim: RESPONSE_FIXTURES } = responses;
/**
* Every test suite exports their tests in the default object.
@@ -13,126 +15,182 @@ const {preparePaymentChannelClaim: RESPONSE_FIXTURES} = responses
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'default': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async default(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012'
}
maxFee: "0.000012",
};
const response = await client.preparePaymentChannelClaim(
address,
REQUEST_FIXTURES.normal,
localInstructions
)
assertResultMatch(response, RESPONSE_FIXTURES.normal, 'prepare')
);
assertResultMatch(response, RESPONSE_FIXTURES.normal, "prepare");
},
'with renew': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with renew": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012'
}
maxFee: "0.000012",
};
const response = await client.preparePaymentChannelClaim(
address,
REQUEST_FIXTURES.renew,
localInstructions
)
assertResultMatch(response, RESPONSE_FIXTURES.renew, 'prepare')
);
assertResultMatch(response, RESPONSE_FIXTURES.renew, "prepare");
},
'with close': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with close": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012'
}
maxFee: "0.000012",
};
const response = await client.preparePaymentChannelClaim(
address,
REQUEST_FIXTURES.close,
localInstructions
)
assertResultMatch(response, RESPONSE_FIXTURES.close, 'prepare')
);
assertResultMatch(response, RESPONSE_FIXTURES.close, "prepare");
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const response = await client.preparePaymentChannelClaim(
address,
REQUEST_FIXTURES.normal,
localInstructions
)
assertResultMatch(response, RESPONSE_FIXTURES.ticket, 'prepare')
);
assertResultMatch(response, RESPONSE_FIXTURES.ticket, "prepare");
},
'rejects Promise on preparePaymentChannelClaim with renew and close': async (
"rejects Promise on preparePaymentChannelClaim with renew and close": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
try {
const prepared = await client.preparePaymentChannelClaim(
address,
REQUEST_FIXTURES.full
)
);
throw new Error(
'Expected method to reject. Prepared transaction: ' +
JSON.stringify(prepared)
)
`Expected method to reject. Prepared transaction: ${JSON.stringify(
prepared
)}`
);
} catch (err) {
assert.strictEqual(err.name, 'ValidationError')
assert.strictEqual(err.name, "ValidationError");
assert.strictEqual(
err.message,
'"renew" and "close" flags on PaymentChannelClaim are mutually exclusive'
)
);
}
},
'rejects Promise on preparePaymentChannelClaim with no signature': async (
"rejects Promise on preparePaymentChannelClaim with no signature": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
try {
const prepared = await client.preparePaymentChannelClaim(
address,
REQUEST_FIXTURES.noSignature
)
);
throw new Error(
'Expected method to reject. Prepared transaction: ' +
JSON.stringify(prepared)
)
`Expected method to reject. Prepared transaction: ${JSON.stringify(
prepared
)}`
);
} catch (err) {
assert.strictEqual(err.name, 'ValidationError')
assert.strictEqual(err.name, "ValidationError");
assert.strictEqual(
err.message,
'"signature" and "publicKey" fields on PaymentChannelClaim must only be specified together.'
)
);
}
}
}
},
};

View File

@@ -1,15 +1,16 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
export const config = {
// TODO: The mock server right now returns a hard-coded string, no matter
// what "Account" value you pass. We'll need it to support more accurate
// responses before we can turn these tests on.
skipXAddress: true
}
skipXAddress: true,
};
/**
* Every test suite exports their tests in the default object.
@@ -17,62 +18,93 @@ export const config = {
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'preparePaymentChannelCreate': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async preparePaymentChannelCreate(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012'
}
maxFee: "0.000012",
};
const result = await client.preparePaymentChannelCreate(
address,
requests.preparePaymentChannelCreate.normal,
localInstructions
)
);
assertResultMatch(
result,
responses.preparePaymentChannelCreate.normal,
'prepare'
)
"prepare"
);
},
'preparePaymentChannelCreate full': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"preparePaymentChannelCreate full": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.preparePaymentChannelCreate(
address,
requests.preparePaymentChannelCreate.full
)
);
assertResultMatch(
result,
responses.preparePaymentChannelCreate.full,
'prepare'
)
"prepare"
);
},
'preparePaymentChannelCreate with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"preparePaymentChannelCreate with ticket": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.preparePaymentChannelCreate(
address,
requests.preparePaymentChannelCreate.normal,
localInstructions
)
);
assertResultMatch(
result,
responses.preparePaymentChannelCreate.ticket,
'prepare'
)
}
}
"prepare"
);
},
};

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,62 +11,89 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'preparePaymentChannelFund': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async preparePaymentChannelFund(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012'
}
maxFee: "0.000012",
};
const result = await client.preparePaymentChannelFund(
address,
requests.preparePaymentChannelFund.normal,
localInstructions
)
);
assertResultMatch(
result,
responses.preparePaymentChannelFund.normal,
'prepare'
)
"prepare"
);
},
'preparePaymentChannelFund full': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"preparePaymentChannelFund full": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.preparePaymentChannelFund(
address,
requests.preparePaymentChannelFund.full
)
);
assertResultMatch(
result,
responses.preparePaymentChannelFund.full,
'prepare'
)
"prepare"
);
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.preparePaymentChannelFund(
address,
requests.preparePaymentChannelFund.normal,
localInstructions
)
);
assertResultMatch(
result,
responses.preparePaymentChannelFund.ticket,
'prepare'
)
}
}
"prepare"
);
},
};

View File

@@ -1,9 +1,12 @@
import assert from 'assert-diff'
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import assert from "assert-diff";
import { FormattedSettings } from "../../src/common/types/objects";
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -11,334 +14,513 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'simple test': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"simple test": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const response = await client.prepareSettings(
address,
requests.prepareSettings.domain,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(response, responses.prepareSettings.flags, 'prepare')
);
assertResultMatch(response, responses.prepareSettings.flags, "prepare");
},
'no maxLedgerVersion': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"no maxLedgerVersion": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const response = await client.prepareSettings(
address,
requests.prepareSettings.domain,
{
maxLedgerVersion: null
maxLedgerVersion: null as unknown as undefined,
}
)
);
assertResultMatch(
response,
responses.prepareSettings.noMaxLedgerVersion,
'prepare'
)
"prepare"
);
},
'no instructions': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"no instructions": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const response = await client.prepareSettings(
address,
requests.prepareSettings.domain
)
);
assertResultMatch(
response,
responses.prepareSettings.noInstructions,
'prepare'
)
"prepare"
);
},
'regularKey': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const regularKey = {regularKey: 'rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD'}
async regularKey(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const regularKey = { regularKey: "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD" };
const response = await client.prepareSettings(
address,
regularKey,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(response, responses.prepareSettings.regularKey, 'prepare')
);
assertResultMatch(
response,
responses.prepareSettings.regularKey,
"prepare"
);
},
'remove regularKey': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const regularKey = {regularKey: null}
"remove regularKey": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const regularKey = { regularKey: null };
const response = await client.prepareSettings(
address,
regularKey,
regularKey as unknown as FormattedSettings,
instructionsWithMaxLedgerVersionOffset
)
);
assertResultMatch(
response,
responses.prepareSettings.removeRegularKey,
'prepare'
)
"prepare"
);
},
'flag set': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = {requireDestinationTag: true}
"flag set": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = { requireDestinationTag: true };
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(response, responses.prepareSettings.flagSet, 'prepare')
);
assertResultMatch(response, responses.prepareSettings.flagSet, "prepare");
},
'flag clear': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = {requireDestinationTag: false}
"flag clear": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = { requireDestinationTag: false };
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(response, responses.prepareSettings.flagClear, 'prepare')
);
assertResultMatch(response, responses.prepareSettings.flagClear, "prepare");
},
'set depositAuth flag': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = {depositAuth: true}
"set depositAuth flag": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = { depositAuth: true };
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
);
assertResultMatch(
response,
responses.prepareSettings.flagSetDepositAuth,
'prepare'
)
"prepare"
);
},
'clear depositAuth flag': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = {depositAuth: false}
"clear depositAuth flag": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = { depositAuth: false };
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
);
assertResultMatch(
response,
responses.prepareSettings.flagClearDepositAuth,
'prepare'
)
"prepare"
);
},
'integer field clear': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = {transferRate: null}
"integer field clear": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = { transferRate: null };
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
assert(response)
assert.strictEqual(JSON.parse(response.txJSON).TransferRate, 0)
);
assert(response);
assert.strictEqual(JSON.parse(response.txJSON).TransferRate, 0);
},
'set transferRate': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = {transferRate: 1}
"set transferRate": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = { transferRate: 1 };
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
);
assertResultMatch(
response,
responses.prepareSettings.setTransferRate,
'prepare'
)
"prepare"
);
},
'set signers': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = requests.prepareSettings.signers.normal
"set signers": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = requests.prepareSettings.signers.normal;
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(response, responses.prepareSettings.signers, 'prepare')
);
assertResultMatch(response, responses.prepareSettings.signers, "prepare");
},
'signers no threshold': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = requests.prepareSettings.signers.noThreshold
"signers no threshold": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = requests.prepareSettings.signers.noThreshold;
try {
const response = await client.prepareSettings(
address,
settings,
instructionsWithMaxLedgerVersionOffset
)
);
throw new Error(
'Expected method to reject. Prepared transaction: ' +
JSON.stringify(response)
)
`Expected method to reject. Prepared transaction: ${JSON.stringify(
response
)}`
);
} catch (err) {
assert.strictEqual(
err.message,
'instance.settings.signers requires property "threshold"'
)
assert.strictEqual(err.name, 'ValidationError')
);
assert.strictEqual(err.name, "ValidationError");
}
},
'signers no weights': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = requests.prepareSettings.signers.noWeights
"signers no weights": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = requests.prepareSettings.signers.noWeights;
const localInstructions = {
signersCount: 1,
...instructionsWithMaxLedgerVersionOffset
}
...instructionsWithMaxLedgerVersionOffset,
};
const response = await client.prepareSettings(
address,
settings,
localInstructions
)
assertResultMatch(response, responses.prepareSettings.noWeights, 'prepare')
);
assertResultMatch(response, responses.prepareSettings.noWeights, "prepare");
},
'fee for multisign': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"fee for multisign": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
signersCount: 4,
...instructionsWithMaxLedgerVersionOffset
}
...instructionsWithMaxLedgerVersionOffset,
};
const response = await client.prepareSettings(
address,
requests.prepareSettings.domain,
localInstructions
)
);
assertResultMatch(
response,
responses.prepareSettings.flagsMultisign,
'prepare'
)
"prepare"
);
},
'no signer list': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const settings = requests.prepareSettings.noSignerEntries
"no signer list": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const settings = requests.prepareSettings.noSignerEntries;
const localInstructions = {
signersCount: 1,
...instructionsWithMaxLedgerVersionOffset
}
...instructionsWithMaxLedgerVersionOffset,
};
const response = await client.prepareSettings(
address,
settings,
localInstructions
)
);
assertResultMatch(
response,
responses.prepareSettings.noSignerList,
'prepare'
)
"prepare"
);
},
'invalid': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async invalid(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
// domain must be a string
const settings = Object.assign({}, requests.prepareSettings.domain, {
domain: 123
})
const settings = { ...requests.prepareSettings.domain, domain: 123 };
const localInstructions = {
signersCount: 4,
...instructionsWithMaxLedgerVersionOffset
}
...instructionsWithMaxLedgerVersionOffset,
};
try {
const response = await client.prepareSettings(
address,
settings,
localInstructions
)
);
throw new Error(
'Expected method to reject. Prepared transaction: ' +
JSON.stringify(response)
)
`Expected method to reject. Prepared transaction: ${JSON.stringify(
response
)}`
);
} catch (err) {
assert.strictEqual(
err.message,
'instance.settings.domain is not of a type(s) string'
)
assert.strictEqual(err.name, 'ValidationError')
"instance.settings.domain is not of a type(s) string"
);
assert.strictEqual(err.name, "ValidationError");
}
},
'offline': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
async offline(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const settings = requests.prepareSettings.domain
const settings = requests.prepareSettings.domain;
const instructions = {
sequence: 23,
maxLedgerVersion: 8820051,
fee: '0.000012'
}
const result = await client.prepareSettings(address, settings, instructions)
assertResultMatch(result, responses.prepareSettings.flags, 'prepare')
fee: "0.000012",
};
const result = await client.prepareSettings(
address,
settings,
instructions
);
assertResultMatch(result, responses.prepareSettings.flags, "prepare");
assert.deepEqual(
client.sign(result.txJSON, secret),
responses.prepareSettings.signed
)
);
},
'prepare settings with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"prepare settings with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const instructions = {
ticketSequence: 23,
maxLedgerVersion: 8820051,
fee: '0.000012'
}
fee: "0.000012",
};
const response = await client.prepareSettings(
address,
requests.prepareSettings.domain,
instructions
)
assertResultMatch(response, responses.prepareSettings.ticket, 'prepare')
}
}
);
assertResultMatch(response, responses.prepareSettings.ticket, "prepare");
},
};

View File

@@ -1,6 +1,6 @@
import {assertResultMatch, TestSuite} from '../testUtils'
import rippled from "../fixtures/rippled";
import { assertResultMatch, TestSuite } from "../testUtils";
// import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
// import requests from '../fixtures/requests'
// import {ValidationError} from 'xrpl-local/common/errors'
// import binary from 'ripple-binary-codec'
@@ -19,48 +19,70 @@ import rippled from '../fixtures/rippled'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'creates a ticket successfully with a sequence number': async (
"creates a ticket successfully with a sequence number": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const expected = {
txJSON:
'{"TransactionType":"TicketCreate", "TicketCount": 2, "Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Flags":2147483648,"LastLedgerSequence":8819954,"Sequence":23,"Fee":"12"}',
instructions: {
maxLedgerVersion: 8819954,
sequence: 23,
fee: '0.000012'
}
}
const response = await client.prepareTicketCreate(address, 2)
assertResultMatch(response, expected, 'prepare')
fee: "0.000012",
},
};
const response = await client.prepareTicketCreate(address, 2);
assertResultMatch(response, expected, "prepare");
},
'creates a ticket successfully with another ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"creates a ticket successfully with another ticket": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const expected = {
txJSON:
'{"TransactionType":"TicketCreate", "TicketCount": 1, "Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Flags":2147483648,"LastLedgerSequence":8819954,"Sequence": 0,"TicketSequence":23,"Fee":"12"}',
instructions: {
maxLedgerVersion: 8819954,
ticketSequence: 23,
fee: '0.000012'
}
}
fee: "0.000012",
},
};
const instructions = {
maxLedgerVersion: 8819954,
ticketSequence: 23,
fee: '0.000012'
}
const response = await client.prepareTicketCreate(address, 1, instructions)
assertResultMatch(response, expected, 'prepare')
}
}
fee: "0.000012",
};
const response = await client.prepareTicketCreate(address, 1, instructions);
assertResultMatch(response, expected, "prepare");
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,9 @@
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {assertRejects, assertResultMatch, TestSuite} from '../testUtils'
const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { assertRejects, assertResultMatch, TestSuite } from "../testUtils";
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 };
/**
* Every test suite exports their tests in the default object.
@@ -10,51 +11,87 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100}
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'simple': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async simple(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareTrustline(
address,
requests.prepareTrustline.simple,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(result, responses.prepareTrustline.simple, 'prepare')
);
assertResultMatch(result, responses.prepareTrustline.simple, "prepare");
},
'frozen': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async frozen(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareTrustline(
address,
requests.prepareTrustline.frozen
)
assertResultMatch(result, responses.prepareTrustline.frozen, 'prepare')
);
assertResultMatch(result, responses.prepareTrustline.frozen, "prepare");
},
'complex': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
async complex(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareTrustline(
address,
requests.prepareTrustline.complex,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(result, responses.prepareTrustline.complex, 'prepare')
);
assertResultMatch(result, responses.prepareTrustline.complex, "prepare");
},
'invalid': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const trustline = Object.assign({}, requests.prepareTrustline.complex)
delete trustline.limit // Make invalid
async invalid(client, address, mockRippled) {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const trustline = { ...requests.prepareTrustline.complex };
delete trustline.limit; // Make invalid
await assertRejects(
client.prepareTrustline(
@@ -64,37 +101,59 @@ export default <TestSuite>{
),
client.errors.ValidationError,
'instance.trustline requires property "limit"'
)
);
},
'xaddress-issuer': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"xaddress-issuer": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const result = await client.prepareTrustline(
address,
requests.prepareTrustline.issuedXAddress,
instructionsWithMaxLedgerVersionOffset
)
assertResultMatch(result, responses.prepareTrustline.issuedXAddress, 'prepare')
);
assertResultMatch(
result,
responses.prepareTrustline.issuedXAddress,
"prepare"
);
},
'with ticket': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"with ticket": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const localInstructions = {
...instructionsWithMaxLedgerVersionOffset,
maxFee: '0.000012',
ticketSequence: 23
}
maxFee: "0.000012",
ticketSequence: 23,
};
const result = await client.prepareTrustline(
address,
requests.prepareTrustline.simple,
localInstructions
)
assertResultMatch(result, responses.prepareTrustline.ticket, 'prepare')
}
}
);
assertResultMatch(result, responses.prepareTrustline.ticket, "prepare");
},
};

View File

@@ -1,6 +1,6 @@
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {TestSuite, assertResultMatch} from '../testUtils'
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { TestSuite, assertResultMatch } from "../testUtils";
/**
* Every test suite exports their tests in the default object.
@@ -8,31 +8,41 @@ import {TestSuite, assertResultMatch} from '../testUtils'
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'request account_objects': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_objects', account: address}, rippled.account_objects.normal)
const result = await client.request({command: 'account_objects',
account: address
})
"request account_objects": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "account_objects", account: address },
rippled.account_objects.normal
);
const result = await client.request({
command: "account_objects",
account: address,
});
assertResultMatch(
result.result,
responses.getAccountObjects,
'AccountObjectsResponse'
)
"AccountObjectsResponse"
);
},
'request account_objects - invalid options': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'account_objects', account: address}, rippled.account_objects.normal)
// @ts-ignore Intentionally no local validation of these options
const result = await client.request({command: 'account_objects',
"request account_objects - invalid options": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse(
{ command: "account_objects", account: address },
rippled.account_objects.normal
);
const result = await client.request({
command: "account_objects",
account: address,
invalid: 'options'
})
});
assertResultMatch(
result.result,
responses.getAccountObjects,
'AccountObjectsResponse'
)
}
}
"AccountObjectsResponse"
);
},
};

View File

@@ -1,14 +1,14 @@
import assert from 'assert-diff'
import {assertRejects, TestSuite} from '../testUtils'
import rippled from '../fixtures/rippled'
import assert from "assert-diff";
const rippledResponse = function(request: Request) : object {
if ('marker' in request) {
return rippled.ledger_data.last_page
} else {
return rippled.ledger_data.first_page
import rippled from "../fixtures/rippled";
import { assertRejects, TestSuite } from "../testUtils";
const rippledResponse = function (request: Request): object {
if ("marker" in request) {
return rippled.ledger_data.last_page;
}
}
return rippled.ledger_data.first_page;
};
/**
* Every test suite exports their tests in the default object.
@@ -16,37 +16,35 @@ const rippledResponse = function(request: Request) : object {
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'requests the next page': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'ledger_data'}, rippledResponse)
// @ts-ignore
const response = await client.request({command: 'ledger_data'})
"requests the next page": async (client, address, mockRippled) => {
mockRippled.addResponse({ command: "ledger_data" }, rippledResponse);
const response = await client.request({ command: "ledger_data" });
const responseNextPage = await client.requestNextPage(
// @ts-ignore
{command: 'ledger_data'},
{ command: "ledger_data" },
response
)
);
assert.equal(
// @ts-ignore
responseNextPage.result.state[0].index,
'000B714B790C3C79FEE00D17C4DEB436B375466F29679447BA64F265FD63D731'
)
"000B714B790C3C79FEE00D17C4DEB436B375466F29679447BA64F265FD63D731"
);
},
'rejects when there are no more pages': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'ledger_data'}, rippledResponse)
// @ts-ignore
const response = await client.request({command: 'ledger_data'})
"rejects when there are no more pages": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({ command: "ledger_data" }, rippledResponse);
const response = await client.request({ command: "ledger_data" });
const responseNextPage = await client.requestNextPage(
// @ts-ignore
{command: 'ledger_data'},
{ command: "ledger_data" },
response
)
assert(!client.hasNextPage(responseNextPage))
);
assert(!client.hasNextPage(responseNextPage));
await assertRejects(
// @ts-ignore
client.requestNextPage({command: 'ledger_data'}, responseNextPage),
client.requestNextPage({ command: "ledger_data" }, responseNextPage),
Error,
'response does not have a next page'
)
}
}
"response does not have a next page"
);
},
};

View File

@@ -1,13 +1,15 @@
import assert from 'assert-diff'
import binary from 'ripple-binary-codec'
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled'
import {TestSuite} from '../testUtils'
import * as schemaValidator from 'xrpl-local/common/schema-validator'
import assert from "assert-diff";
import binary from "ripple-binary-codec";
const {sign: REQUEST_FIXTURES} = requests
const {sign: RESPONSE_FIXTURES} = responses
import * as schemaValidator from "xrpl-local/common/schema-validator";
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import rippled from "../fixtures/rippled";
import { TestSuite } from "../testUtils";
const { sign: REQUEST_FIXTURES } = requests;
const { sign: RESPONSE_FIXTURES } = responses;
/**
* Every test suite exports their tests in the default object.
@@ -15,413 +17,453 @@ const {sign: RESPONSE_FIXTURES} = responses
* - Check out "test/client/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'sign': async (client, address) => {
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret)
assert.deepEqual(result, RESPONSE_FIXTURES.normal)
schemaValidator.schemaValidate('sign', result)
async sign(client, address) {
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret);
assert.deepEqual(result, RESPONSE_FIXTURES.normal);
schemaValidator.schemaValidate("sign", result);
},
'sign with lowercase hex data in memo (hex should be case insensitive)': async (client, address) => {
const secret = 'shd2nxpFD6iBRKWsRss2P4tKMWyy9';
const lowercaseMemoTxJson = {
"TransactionType" : "Payment",
"Flags" : 2147483648,
"Account" : "rwiZ3q3D3QuG4Ga2HyGdq3kPKJRGctVG8a",
"Amount" : "10000000",
"LastLedgerSequence": 14000999,
"Destination" : "rUeEBYXHo8vF86Rqir3zWGRQ84W9efdAQd",
"Fee" : "12",
"Sequence" : 12,
"SourceTag" : 8888,
"DestinationTag" : 9999,
"Memos" : [
{
"Memo": {
"MemoType" :"687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
"MemoData" :"72656e74"
}
}
]
}
"sign with lowercase hex data in memo (hex should be case insensitive)":
async (client, address) => {
const secret = "shd2nxpFD6iBRKWsRss2P4tKMWyy9";
const lowercaseMemoTxJson = {
TransactionType: "Payment",
Flags: 2147483648,
Account: "rwiZ3q3D3QuG4Ga2HyGdq3kPKJRGctVG8a",
Amount: "10000000",
LastLedgerSequence: 14000999,
Destination: "rUeEBYXHo8vF86Rqir3zWGRQ84W9efdAQd",
Fee: "12",
Sequence: 12,
SourceTag: 8888,
DestinationTag: 9999,
Memos: [
{
Memo: {
MemoType:
"687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
MemoData: "72656e74",
},
},
],
};
const txParams = JSON.stringify(lowercaseMemoTxJson);
const result = client.sign(txParams, secret);
assert.deepEqual(result, {
signedTransaction: '120000228000000023000022B8240000000C2E0000270F201B00D5A36761400000000098968068400000000000000C73210305E09ED602D40AB1AF65646A4007C2DAC17CB6CDACDE301E74FB2D728EA057CF744730450221009C00E8439E017CA622A5A1EE7643E26B4DE9C808DE2ABE45D33479D49A4CEC66022062175BE8733442FA2A4D9A35F85A57D58252AE7B19A66401FE238B36FA28E5A081146C1856D0E36019EA75C56D7E8CBA6E35F9B3F71583147FB49CD110A1C46838788CD12764E3B0F837E0DDF9EA7C1F687474703A2F2F6578616D706C652E636F6D2F6D656D6F2F67656E657269637D0472656E74E1F1',
id: '41B9CB78D8E18A796CDD4B0BC6FB0EA19F64C4F25FDE23049197852CAB71D10D'
})
},
const txParams = JSON.stringify(lowercaseMemoTxJson);
const result = client.sign(txParams, secret);
assert.deepEqual(result, {
signedTransaction:
"120000228000000023000022B8240000000C2E0000270F201B00D5A36761400000000098968068400000000000000C73210305E09ED602D40AB1AF65646A4007C2DAC17CB6CDACDE301E74FB2D728EA057CF744730450221009C00E8439E017CA622A5A1EE7643E26B4DE9C808DE2ABE45D33479D49A4CEC66022062175BE8733442FA2A4D9A35F85A57D58252AE7B19A66401FE238B36FA28E5A081146C1856D0E36019EA75C56D7E8CBA6E35F9B3F71583147FB49CD110A1C46838788CD12764E3B0F837E0DDF9EA7C1F687474703A2F2F6578616D706C652E636F6D2F6D656D6F2F67656E657269637D0472656E74E1F1",
id: "41B9CB78D8E18A796CDD4B0BC6FB0EA19F64C4F25FDE23049197852CAB71D10D",
});
},
'sign with paths': async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
"sign with paths": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const payment = {
source: {
address: address,
address,
amount: {
currency: 'drops',
value: '100'
}
currency: "drops",
value: "100",
},
},
destination: {
address: 'rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj',
address: "rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj",
minAmount: {
currency: 'USD',
value: '0.00004579644712312366',
counterparty: 'rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc'
}
currency: "USD",
value: "0.00004579644712312366",
counterparty: "rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc",
},
},
// eslint-disable-next-line no-useless-escape
paths: '[[{\"currency\":\"USD\",\"issuer\":\"rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc\"}]]'
}
const ret = await client.preparePayment(address, payment, {sequence: 1, maxLedgerVersion: 15696358})
const result = client.sign(ret.txJSON, secret)
paths:
'[[{"currency":"USD","issuer":"rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc"}]]',
};
const ret = await client.preparePayment(address, payment, {
sequence: 1,
maxLedgerVersion: 15696358,
});
const result = client.sign(ret.txJSON, secret);
assert.deepEqual(result, {
signedTransaction: '12000022800200002400000001201B00EF81E661EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200A693FB5CA6B21250EBDFD8CFF526EE0DF7C9E4E31EB0660692E75E6A93BF5F802203CC39463DDA21386898CA31E18AD1A6828647D65741DD637BAD71BC83E29DB9481145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900',
id: '78874FE5F5299FEE3EA85D3CF6C1FB1F1D46BB08F716662A3E3D1F0ADE4EF796'
})
schemaValidator.schemaValidate('sign', result)
signedTransaction:
"12000022800200002400000001201B00EF81E661EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200A693FB5CA6B21250EBDFD8CFF526EE0DF7C9E4E31EB0660692E75E6A93BF5F802203CC39463DDA21386898CA31E18AD1A6828647D65741DD637BAD71BC83E29DB9481145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900",
id: "78874FE5F5299FEE3EA85D3CF6C1FB1F1D46BB08F716662A3E3D1F0ADE4EF796",
});
schemaValidator.schemaValidate("sign", result);
},
'already signed': async (client, address) => {
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret)
"already signed": async (client, address) => {
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret);
assert.throws(() => {
const tx = JSON.stringify(binary.decode(result.signedTransaction))
client.sign(tx, secret)
}, /txJSON must not contain "TxnSignature" or "Signers" properties/)
const tx = JSON.stringify(binary.decode(result.signedTransaction));
client.sign(tx, secret);
}, /txJSON must not contain "TxnSignature" or "Signers" properties/);
},
'EscrowExecution': async (client, address) => {
const secret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb'
const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, secret)
assert.deepEqual(result, RESPONSE_FIXTURES.escrow)
schemaValidator.schemaValidate('sign', result)
async EscrowExecution(client, address) {
const secret = "snoPBrXtMeMyMHUVTgbuqAfg1SUTb";
const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, secret);
assert.deepEqual(result, RESPONSE_FIXTURES.escrow);
schemaValidator.schemaValidate("sign", result);
},
'signAs': async (client, address) => {
const txJSON = REQUEST_FIXTURES.signAs
const secret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb'
async signAs(client, address) {
const txJSON = REQUEST_FIXTURES.signAs;
const secret = "snoPBrXtMeMyMHUVTgbuqAfg1SUTb";
const signature = client.sign(JSON.stringify(txJSON), secret, {
signAs: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
})
assert.deepEqual(signature, RESPONSE_FIXTURES.signAs)
signAs: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
});
assert.deepEqual(signature, RESPONSE_FIXTURES.signAs);
},
'withKeypair': async (client, address) => {
async withKeypair(client, address) {
const keypair = {
privateKey:
'00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A',
"00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A",
publicKey:
'02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8'
}
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair)
assert.deepEqual(result, RESPONSE_FIXTURES.normal)
schemaValidator.schemaValidate('sign', result)
"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8",
};
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair);
assert.deepEqual(result, RESPONSE_FIXTURES.normal);
schemaValidator.schemaValidate("sign", result);
},
'withKeypair already signed': async (client, address) => {
"withKeypair already signed": async (client, address) => {
const keypair = {
privateKey:
'00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A',
"00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A",
publicKey:
'02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8'
}
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair)
"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8",
};
const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair);
assert.throws(() => {
const tx = JSON.stringify(binary.decode(result.signedTransaction))
client.sign(tx, keypair)
}, /txJSON must not contain "TxnSignature" or "Signers" properties/)
const tx = JSON.stringify(binary.decode(result.signedTransaction));
client.sign(tx, keypair);
}, /txJSON must not contain "TxnSignature" or "Signers" properties/);
},
'withKeypair EscrowExecution': async (client, address) => {
"withKeypair EscrowExecution": async (client, address) => {
const keypair = {
privateKey:
'001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7',
"001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7",
publicKey:
'0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020'
}
const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, keypair)
assert.deepEqual(result, RESPONSE_FIXTURES.escrow)
schemaValidator.schemaValidate('sign', result)
"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
};
const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, keypair);
assert.deepEqual(result, RESPONSE_FIXTURES.escrow);
schemaValidator.schemaValidate("sign", result);
},
'withKeypair signAs': async (client, address) => {
const txJSON = REQUEST_FIXTURES.signAs
"withKeypair signAs": async (client, address) => {
const txJSON = REQUEST_FIXTURES.signAs;
const keypair = {
privateKey:
'001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7',
"001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7",
publicKey:
'0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020'
}
"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
};
const signature = client.sign(JSON.stringify(txJSON), keypair, {
signAs: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
})
assert.deepEqual(signature, RESPONSE_FIXTURES.signAs)
signAs: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
});
assert.deepEqual(signature, RESPONSE_FIXTURES.signAs);
},
'succeeds - prepared payment': async (client, address, mockRippled) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
"succeeds - prepared payment": async (client, address, mockRippled) => {
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const payment = await client.preparePayment(address, {
source: {
address: address,
address,
maxAmount: {
value: '1',
currency: 'drops'
}
value: "1",
currency: "drops",
},
},
destination: {
address: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
address: "rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r",
amount: {
value: '1',
currency: 'drops'
}
}
})
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const result = client.sign(payment.txJSON, secret)
value: "1",
currency: "drops",
},
},
});
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const result = client.sign(payment.txJSON, secret);
const expectedResult = {
signedTransaction:
'12000022800000002400000017201B008694F261400000000000000168400000000000000C732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100A9C91D4CFAE45686146EE0B56D4C53A2E7C2D672FB834D43E0BE2D2E9106519A022075DDA2F92DE552B0C45D83D4E6D35889B3FBF51BFBBD9B25EBF70DE3C96D0D6681145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648',
id: '88D6B913C66279EA31ADC25C5806C48B2D4E5680261666790A736E1961217700'
}
assert.deepEqual(result, expectedResult)
schemaValidator.schemaValidate('sign', result)
"12000022800000002400000017201B008694F261400000000000000168400000000000000C732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100A9C91D4CFAE45686146EE0B56D4C53A2E7C2D672FB834D43E0BE2D2E9106519A022075DDA2F92DE552B0C45D83D4E6D35889B3FBF51BFBBD9B25EBF70DE3C96D0D6681145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648",
id: "88D6B913C66279EA31ADC25C5806C48B2D4E5680261666790A736E1961217700",
};
assert.deepEqual(result, expectedResult);
schemaValidator.schemaValidate("sign", result);
},
'succeeds - no flags': async (client, address) => {
"succeeds - no flags": async (client, address) => {
const txJSON =
'{"TransactionType":"Payment","Account":"r45Rev1EXGxy2hAUmJPCne97KUE7qyrD3j","Destination":"rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r","Amount":"20000000","Sequence":1,"Fee":"12"}'
const secret = 'shotKgaEotpcYsshSE39vmSnBDRim'
const result = client.sign(txJSON, secret)
'{"TransactionType":"Payment","Account":"r45Rev1EXGxy2hAUmJPCne97KUE7qyrD3j","Destination":"rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r","Amount":"20000000","Sequence":1,"Fee":"12"}';
const secret = "shotKgaEotpcYsshSE39vmSnBDRim";
const result = client.sign(txJSON, secret);
const expectedResult = {
signedTransaction:
'1200002400000001614000000001312D0068400000000000000C7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100C104B7B97C31FACA4597E7D6FCF13BD85BD11375963A62A0AC45B0061236E39802207784F157F6A98DFC85B051CDDF61CC3084C4F5750B82674801C8E9950280D1998114EE3046A5DDF8422C40DDB93F1D522BB4FE6419158314FDB08D07AAA0EB711793A3027304D688E10C3648',
id: '0596925967F541BF332FF6756645B2576A9858414B5B363DC3D34915BE8A70D6'
}
const decoded = binary.decode(result.signedTransaction)
"1200002400000001614000000001312D0068400000000000000C7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100C104B7B97C31FACA4597E7D6FCF13BD85BD11375963A62A0AC45B0061236E39802207784F157F6A98DFC85B051CDDF61CC3084C4F5750B82674801C8E9950280D1998114EE3046A5DDF8422C40DDB93F1D522BB4FE6419158314FDB08D07AAA0EB711793A3027304D688E10C3648",
id: "0596925967F541BF332FF6756645B2576A9858414B5B363DC3D34915BE8A70D6",
};
const decoded = binary.decode(result.signedTransaction);
assert(
decoded.Flags == null,
`Flags = ${decoded.Flags}, should be undefined`
)
assert.deepEqual(result, expectedResult)
schemaValidator.schemaValidate('sign', result)
);
assert.deepEqual(result, expectedResult);
schemaValidator.schemaValidate("sign", result);
},
'sign succeeds with source.amount/destination.minAmount': async (
"sign succeeds with source.amount/destination.minAmount": async (
client,
address
) => {
// See also: 'preparePayment with source.amount/destination.minAmount'
const txJSON =
'{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rEX4LtGJubaUcMWCJULcy4NVxGT9ZEMVRq","Amount":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000"},"Flags":2147614720,"SendMax":{"currency":"GBP","issuer":"rpat5TmYjDsnFSStmgTumFgXCM9eqsWPro","value":"0.1"},"DeliverMin":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"0.1248548562296331"},"Sequence":23,"LastLedgerSequence":8820051,"Fee":"12"}'
const secret = 'shotKgaEotpcYsshSE39vmSnBDRim'
const result = client.sign(txJSON, secret)
'{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rEX4LtGJubaUcMWCJULcy4NVxGT9ZEMVRq","Amount":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000"},"Flags":2147614720,"SendMax":{"currency":"GBP","issuer":"rpat5TmYjDsnFSStmgTumFgXCM9eqsWPro","value":"0.1"},"DeliverMin":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"0.1248548562296331"},"Sequence":23,"LastLedgerSequence":8820051,"Fee":"12"}';
const secret = "shotKgaEotpcYsshSE39vmSnBDRim";
const result = client.sign(txJSON, secret);
const expectedResult = {
signedTransaction:
'12000022800200002400000017201B0086955361EC6386F26FC0FFFF0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A68400000000000000C69D4438D7EA4C6800000000000000000000000000047425000000000000C155FFE99C8C91F67083CEFFDB69EBFE76348CA6AD4446F8C5D8A5E0B0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100D9634523D8E232D4A7807A71856023D82AC928FA29848571B820867898413B5F022041AC00EC1F81A26A6504EBF844A38CC3204694EF2CC1A97A87632721631F93DA81145E7B112523F68D2F5E879DB4EAC51C6698A6930483149F500E50C2F016CA01945E5A1E5846B61EF2D376',
id: '1C558AA9B926C24FB6BBD6950B2DB1350A83F9F12E4385208867907019761A2D'
}
const decoded = binary.decode(result.signedTransaction)
"12000022800200002400000017201B0086955361EC6386F26FC0FFFF0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A68400000000000000C69D4438D7EA4C6800000000000000000000000000047425000000000000C155FFE99C8C91F67083CEFFDB69EBFE76348CA6AD4446F8C5D8A5E0B0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100D9634523D8E232D4A7807A71856023D82AC928FA29848571B820867898413B5F022041AC00EC1F81A26A6504EBF844A38CC3204694EF2CC1A97A87632721631F93DA81145E7B112523F68D2F5E879DB4EAC51C6698A6930483149F500E50C2F016CA01945E5A1E5846B61EF2D376",
id: "1C558AA9B926C24FB6BBD6950B2DB1350A83F9F12E4385208867907019761A2D",
};
const decoded = binary.decode(result.signedTransaction);
assert(
decoded.Flags === 2147614720,
`Flags = ${decoded.Flags}, should be 2147614720`
)
assert.deepEqual(result, expectedResult)
schemaValidator.schemaValidate('sign', result)
);
assert.deepEqual(result, expectedResult);
schemaValidator.schemaValidate("sign", result);
},
'throws when encoded tx does not match decoded tx - prepared payment': async (
"throws when encoded tx does not match decoded tx - prepared payment": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const payment = await client.preparePayment(address, {
source: {
address: address,
address,
maxAmount: {
value: '1.1234567',
currency: 'drops'
}
value: "1.1234567",
currency: "drops",
},
},
destination: {
address: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
address: "rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r",
amount: {
value: '1.1234567',
currency: 'drops'
}
}
})
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
value: "1.1234567",
currency: "drops",
},
},
});
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
assert.throws(() => {
client.sign(payment.txJSON, secret)
}, /^Error: 1\.1234567 is an illegal amount/)
client.sign(payment.txJSON, secret);
}, /^Error: 1\.1234567 is an illegal amount/);
},
'throws when encoded tx does not match decoded tx - prepared order': async (
"throws when encoded tx does not match decoded tx - prepared order": async (
client,
address,
mockRippled
) => {
mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal)
mockRippled.addResponse({command: 'fee'}, rippled.fee)
mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current)
mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal)
mockRippled.addResponse(
{ command: "server_info" },
rippled.server_info.normal
);
mockRippled.addResponse({ command: "fee" }, rippled.fee);
mockRippled.addResponse(
{ command: "ledger_current" },
rippled.ledger_current
);
mockRippled.addResponse(
{ command: "account_info" },
rippled.account_info.normal
);
const order = {
direction: 'sell',
direction: "sell",
quantity: {
currency: 'USD',
counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
value: '3.140000'
currency: "USD",
counterparty: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
value: "3.140000",
},
totalPrice: {
currency: 'XRP',
value: '31415'
}
}
const prepared = await client.prepareOrder(address, order, {sequence: 123})
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
currency: "XRP",
value: "31415",
},
};
const prepared = await client.prepareOrder(address, order, {
sequence: 123,
});
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
try {
client.sign(prepared.txJSON, secret)
return Promise.reject(new Error('client.sign should have thrown'))
client.sign(prepared.txJSON, secret);
return await Promise.reject(new Error("client.sign should have thrown"));
} catch (error) {
assert.equal(error.name, 'ValidationError')
assert.equal(error.name, "ValidationError");
assert.equal(
error.message,
'Serialized transaction does not match original txJSON. See `error.data`'
)
"Serialized transaction does not match original txJSON. See `error.data`"
);
assert.deepEqual(error.data.diff, {
TakerGets: {
value: '3.14'
}
})
value: "3.14",
},
});
}
},
'throws when encoded tx does not match decoded tx - AccountSet': async (
"throws when encoded tx does not match decoded tx - AccountSet": async (
client,
address
) => {
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const request = {
// TODO: This fails when address is X-address
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1.2","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '0.0000012',
fee: "0.0000012",
sequence: 23,
maxLedgerVersion: 8820051
}
}
maxLedgerVersion: 8820051,
},
};
assert.throws(() => {
client.sign(request.txJSON, secret)
}, /Error: 1\.2 is an illegal amount/)
client.sign(request.txJSON, secret);
}, /Error: 1\.2 is an illegal amount/);
},
'throws when encoded tx does not match decoded tx - higher fee': async (
"throws when encoded tx does not match decoded tx - higher fee": async (
client,
address
) => {
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const request = {
// TODO: This fails when address is X-address
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1123456.7","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '1.1234567',
fee: "1.1234567",
sequence: 23,
maxLedgerVersion: 8820051
}
}
maxLedgerVersion: 8820051,
},
};
assert.throws(() => {
client.sign(request.txJSON, secret)
}, /Error: 1123456\.7 is an illegal amount/)
client.sign(request.txJSON, secret);
}, /Error: 1123456\.7 is an illegal amount/);
},
'throws when Fee exceeds maxFeeXRP (in drops)': async (client, address) => {
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
"throws when Fee exceeds maxFeeXRP (in drops)": async (client, address) => {
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const request = {
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"${address}","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '2.01',
fee: "2.01",
sequence: 23,
maxLedgerVersion: 8820051
}
}
maxLedgerVersion: 8820051,
},
};
assert.throws(() => {
client.sign(request.txJSON, secret)
}, /Fee" should not exceed "2000000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./)
client.sign(request.txJSON, secret);
}, /Fee" should not exceed "2000000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./);
},
'throws when Fee exceeds maxFeeXRP (in drops) - custom maxFeeXRP': async (
"throws when Fee exceeds maxFeeXRP (in drops) - custom maxFeeXRP": async (
client,
address
) => {
client._maxFeeXRP = '1.9'
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
client._maxFeeXRP = "1.9";
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const request = {
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"${address}","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '2.01',
fee: "2.01",
sequence: 23,
maxLedgerVersion: 8820051
}
}
maxLedgerVersion: 8820051,
},
};
assert.throws(() => {
client.sign(request.txJSON, secret)
}, /Fee" should not exceed "1900000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./)
client.sign(request.txJSON, secret);
}, /Fee" should not exceed "1900000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./);
},
'permits fee exceeding 2000000 drops when maxFeeXRP is higher than 2 XRP': async (
client,
address
) => {
client._maxFeeXRP = '2.1'
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
const request = {
// TODO: This fails when address is X-address
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: '2.01',
sequence: 23,
maxLedgerVersion: 8820051
}
}
"permits fee exceeding 2000000 drops when maxFeeXRP is higher than 2 XRP":
async (client, address) => {
client._maxFeeXRP = "2.1";
const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV";
const request = {
// TODO: This fails when address is X-address
txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`,
instructions: {
fee: "2.01",
sequence: 23,
maxLedgerVersion: 8820051,
},
};
const result = client.sign(request.txJSON, secret)
const result = client.sign(request.txJSON, secret);
const expectedResponse = {
signedTransaction:
'12000322800000002400000017201B008695536840000000001EAB90732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200203F219F5371D2C6506888B1B02B27E74998F7A42D412C32FE319AC1A5B8DEF02205959A1B02253ACCCE542759E9886466C56D16B04676FA492AD34AA0E877E91F381145E7B112523F68D2F5E879DB4EAC51C6698A69304',
id: '061D5593E0A117F389826419CAC049A73C7CFCA65A20B788781D41240143D864'
}
const expectedResponse = {
signedTransaction:
"12000322800000002400000017201B008695536840000000001EAB90732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200203F219F5371D2C6506888B1B02B27E74998F7A42D412C32FE319AC1A5B8DEF02205959A1B02253ACCCE542759E9886466C56D16B04676FA492AD34AA0E877E91F381145E7B112523F68D2F5E879DB4EAC51C6698A69304",
id: "061D5593E0A117F389826419CAC049A73C7CFCA65A20B788781D41240143D864",
};
assert.deepEqual(result, expectedResponse)
schemaValidator.schemaValidate('sign', result)
assert.deepEqual(result, expectedResponse);
schemaValidator.schemaValidate("sign", result);
},
"sign with ticket": async (client, address) => {
const secret = "sn7n5R1cR5Y3fRFkuWXA94Ts1frVJ";
const result = client.sign(REQUEST_FIXTURES.ticket.txJSON, secret);
assert.deepEqual(result, RESPONSE_FIXTURES.ticket);
schemaValidator.schemaValidate("sign", result);
},
'sign with ticket': async (client, address) => {
const secret = 'sn7n5R1cR5Y3fRFkuWXA94Ts1frVJ'
const result = client.sign(REQUEST_FIXTURES.ticket.txJSON, secret)
assert.deepEqual(result, RESPONSE_FIXTURES.ticket)
schemaValidator.schemaValidate('sign', result)
}
}
};

View File

@@ -1,541 +1,529 @@
import _ from 'lodash'
import net from 'net'
import assert from 'assert-diff'
import setupClient from './setupClient'
import {Client} from 'xrpl-local'
import {ignoreWebSocketDisconnect} from './testUtils'
import {Connection} from 'xrpl-local/client'
import rippled from './fixtures/rippled'
import net from "net";
const TIMEOUT = 200000 // how long before each test case times out
const isBrowser = (process as any).browser
import assert from "assert-diff";
import _ from "lodash";
import { Client } from "xrpl-local";
import { Connection } from "xrpl-local/client";
import rippled from "./fixtures/rippled";
import setupClient from "./setupClient";
import { ignoreWebSocketDisconnect } from "./testUtils";
const TIMEOUT = 200000; // how long before each test case times out
const isBrowser = (process as any).browser;
function createServer() {
return new Promise((resolve, reject) => {
const server = net.createServer()
server.on('listening', function () {
resolve(server)
})
server.on('error', function (error) {
reject(error)
})
server.listen(0, '0.0.0.0')
})
const server = net.createServer();
server.on("listening", function () {
resolve(server);
});
server.on("error", function (error) {
reject(error);
});
server.listen(0, "0.0.0.0");
});
}
describe('Connection', function () {
this.timeout(TIMEOUT)
beforeEach(setupClient.setup)
afterEach(setupClient.teardown)
describe("Connection", function () {
this.timeout(TIMEOUT);
beforeEach(setupClient.setup);
afterEach(setupClient.teardown);
it('default options', function () {
const connection: any = new Connection('url')
assert.strictEqual(connection._url, 'url')
assert(connection._config.proxy == null)
assert(connection._config.authorization == null)
})
it("default options", function () {
const connection: any = new Connection("url");
assert.strictEqual(connection._url, "url");
assert(connection._config.proxy == null);
assert(connection._config.authorization == null);
});
describe('trace', () => {
const mockedRequestData = {mocked: 'request'}
const mockedResponse = JSON.stringify({mocked: 'response', id: 0})
describe("trace", function () {
const mockedRequestData = { mocked: "request" };
const mockedResponse = JSON.stringify({ mocked: "response", id: 0 });
const expectedMessages = [
// We add the ID here, since it's not a part of the user-provided request.
['send', JSON.stringify({...mockedRequestData, id: 0})],
['receive', mockedResponse]
]
const originalConsoleLog = console.log
["send", JSON.stringify({ ...mockedRequestData, id: 0 })],
["receive", mockedResponse],
];
const originalConsoleLog = console.log;
afterEach(() => {
console.log = originalConsoleLog
})
afterEach(function () {
console.log = originalConsoleLog;
});
it('as false', function () {
const messages = []
console.log = (id, message) => messages.push([id, message])
const connection: any = new Connection('url', {trace: false})
connection._ws = {send: function () {}}
connection.request(mockedRequestData)
connection._onMessage(mockedResponse)
assert.deepEqual(messages, [])
})
it("as false", function () {
const messages: any[] = [];
console.log = (id, message) => messages.push([id, message]);
const connection: any = new Connection("url", { trace: false });
connection._ws = { send() {} };
connection.request(mockedRequestData);
connection._onMessage(mockedResponse);
assert.deepEqual(messages, []);
});
it('as true', function () {
const messages = []
console.log = (id, message) => messages.push([id, message])
const connection: any = new Connection('url', {trace: true})
connection._ws = {send: function () {}}
connection.request(mockedRequestData)
connection._onMessage(mockedResponse)
assert.deepEqual(messages, expectedMessages)
})
it("as true", function () {
const messages: any[] = [];
console.log = (id, message) => messages.push([id, message]);
const connection: any = new Connection("url", { trace: true });
connection._ws = { send() {} };
connection.request(mockedRequestData);
connection._onMessage(mockedResponse);
assert.deepEqual(messages, expectedMessages);
});
it('as a function', function () {
const messages = []
const connection: any = new Connection('url', {
trace: (id, message) => messages.push([id, message])
})
connection._ws = {send: function () {}}
connection.request(mockedRequestData)
connection._onMessage(mockedResponse)
assert.deepEqual(messages, expectedMessages)
})
})
it("as a function", function () {
const messages: any[] = [];
const connection: any = new Connection("url", {
trace: (id, message) => messages.push([id, message]),
});
connection._ws = { send() {} };
connection.request(mockedRequestData);
connection._onMessage(mockedResponse);
assert.deepEqual(messages, expectedMessages);
});
});
it('with proxy', function (done) {
it("with proxy", function (done) {
if (isBrowser) {
done()
return
done();
return;
}
createServer().then((server: any) => {
const port = server.address().port
const expect = 'CONNECT localhost'
server.on('connection', (socket) => {
socket.on('data', (data) => {
const got = data.toString('ascii', 0, expect.length)
assert.strictEqual(got, expect)
server.close()
connection.disconnect()
done()
})
})
const port = server.address().port;
const expect = "CONNECT localhost";
server.on("connection", (socket) => {
socket.on("data", (data) => {
const got = data.toString("ascii", 0, expect.length);
assert.strictEqual(got, expect);
server.close();
connection.disconnect();
done();
});
});
const options = {
proxy: 'ws://localhost:' + port,
authorization: 'authorization',
trustedCertificates: ['path/to/pem']
}
const connection = new Connection(
this.client.connection._url,
options
)
proxy: `ws://localhost:${port}`,
authorization: "authorization",
trustedCertificates: ["path/to/pem"],
};
const connection = new Connection(this.client.connection._url, options);
connection.connect().catch((err) => {
assert(err instanceof this.client.errors.NotConnectedError)
})
}, done)
})
assert(err instanceof this.client.errors.NotConnectedError);
});
}, done);
});
it('Multiply disconnect calls', function () {
this.client.disconnect()
return this.client.disconnect()
})
it("Multiply disconnect calls", function () {
this.client.disconnect();
return this.client.disconnect();
});
it('reconnect', function () {
return this.client.connection.reconnect()
})
it("reconnect", function () {
return this.client.connection.reconnect();
});
it('NotConnectedError', function () {
const connection = new Connection('url')
return connection.request({
command: 'ledger',
ledger_index: 'validated'
it("NotConnectedError", function () {
const connection = new Connection("url");
return connection
.request({
command: "ledger",
ledger_index: "validated",
})
.then(() => {
assert(false, 'Should throw NotConnectedError')
assert(false, "Should throw NotConnectedError");
})
.catch((error) => {
assert(error instanceof this.client.errors.NotConnectedError)
})
})
assert(error instanceof this.client.errors.NotConnectedError);
});
});
it('should throw NotConnectedError if server not responding ', function (done) {
it("should throw NotConnectedError if server not responding ", function (done) {
if (isBrowser) {
const phantomTest = /PhantomJS/
if (phantomTest.test(navigator.userAgent)) {
if (navigator.userAgent.includes("PhantomJS")) {
// inside PhantomJS this one just hangs, so skip as not very relevant
done()
return
done();
return;
}
}
// Address where no one listens
const connection = new Connection(
'ws://testripple.circleci.com:129'
)
connection.on('error', done)
const connection = new Connection("ws://testripple.circleci.com:129");
connection.on("error", done);
connection.connect().catch((error) => {
assert(error instanceof this.client.errors.NotConnectedError)
done()
})
})
assert(error instanceof this.client.errors.NotConnectedError);
done();
});
});
it('DisconnectedError', async function () {
this.mockRippled.suppressOutput = true
it("DisconnectedError", async function () {
this.mockRippled.suppressOutput = true;
this.mockRippled.on(`request_server_info`, function (request, conn) {
assert.strictEqual(request.command, 'server_info')
conn.close()
})
assert.strictEqual(request.command, "server_info");
conn.close();
});
return this.client
.request({command: "server_info"})
.request({ command: "server_info" })
.then(() => {
assert(false, 'Should throw DisconnectedError')
assert(false, "Should throw DisconnectedError");
})
.catch((error) => {
assert(error instanceof this.client.errors.DisconnectedError)
})
})
assert(error instanceof this.client.errors.DisconnectedError);
});
});
it('TimeoutError', function () {
this.client.connection._ws.send = function (message, options, callback) {
callback(null)
}
const request = {command: 'server_info'}
it("TimeoutError", function () {
this.client.connection._ws.send = function (message, callback) {
callback(null);
};
const request = { command: "server_info" };
return this.client.connection
.request(request, 10)
.then(() => {
assert(false, 'Should throw TimeoutError')
assert(false, "Should throw TimeoutError");
})
.catch((error) => {
assert(error instanceof this.client.errors.TimeoutError)
})
})
assert(error instanceof this.client.errors.TimeoutError);
});
});
it('DisconnectedError on send', function () {
this.client.connection._ws.send = function (message, options, callback) {
callback({message: 'not connected'})
}
it("DisconnectedError on send", function () {
this.client.connection._ws.send = function (message, callback) {
callback({ message: "not connected" });
};
return this.client
.request({command: "server_info"})
.request({ command: "server_info" })
.then(() => {
assert(false, 'Should throw DisconnectedError')
assert(false, "Should throw DisconnectedError");
})
.catch((error) => {
assert(error instanceof this.client.errors.DisconnectedError)
assert.strictEqual(error.message, 'not connected')
})
})
console.log(error);
assert(error instanceof this.client.errors.DisconnectedError);
assert.strictEqual(error.message, "not connected");
});
});
it('DisconnectedError on initial _onOpen send', async function () {
it("DisconnectedError on initial _onOpen send", async function () {
// _onOpen previously could throw PromiseRejectionHandledWarning: Promise rejection was handled asynchronously
// do not rely on the client.setup hook to test this as it bypasses the case, disconnect client connection first
await this.client.disconnect()
await this.client.disconnect();
// stub _onOpen to only run logic relevant to test case
this.client.connection._onOpen = () => {
// overload websocket send on open when _ws exists
this.client.connection._ws.send = function (data, options, cb) {
// recent ws throws this error instead of calling back
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)')
}
const request = {command: 'subscribe', streams: ['ledger']}
return this.client.connection.request(request)
}
throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
};
const request = { command: "subscribe", streams: ["ledger"] };
return this.client.connection.request(request);
};
try {
await this.client.connect()
await this.client.connect();
} catch (error) {
assert(error instanceof this.client.errors.DisconnectedError)
assert(error instanceof this.client.errors.DisconnectedError);
assert.strictEqual(
error.message,
'WebSocket is not open: readyState 0 (CONNECTING)'
)
"WebSocket is not open: readyState 0 (CONNECTING)"
);
}
})
});
it('ResponseFormatError', function () {
it("ResponseFormatError", function () {
return this.client
.request({command: 'test_command', data: {unrecognizedResponse: true}})
.request({
command: "test_command",
data: { unrecognizedResponse: true },
})
.then(() => {
assert(false, 'Should throw ResponseFormatError')
assert(false, "Should throw ResponseFormatError");
})
.catch((error) => {
assert(error instanceof this.client.errors.ResponseFormatError)
})
})
assert(error instanceof this.client.errors.ResponseFormatError);
});
});
it('reconnect on unexpected close', function (done) {
this.client.connection.on('connected', () => {
done()
})
it("reconnect on unexpected close", function (done) {
this.client.connection.on("connected", () => {
done();
});
setTimeout(() => {
this.client.connection._ws.close()
}, 1)
})
this.client.connection._ws.close();
}, 1);
});
describe('reconnection test', function () {
it('reconnect on several unexpected close', function (done) {
describe("reconnection test", function () {
it("reconnect on several unexpected close", function (done) {
if (isBrowser) {
const phantomTest = /PhantomJS/
if (phantomTest.test(navigator.userAgent)) {
if (navigator.userAgent.includes("PhantomJS")) {
// inside PhantomJS this one just hangs, so skip as not very relevant
done()
return
done();
return;
}
}
this.timeout(70001)
const self = this
this.timeout(70001);
const self = this;
function breakConnection() {
self.client.connection
.request({
command: 'test_command',
data: {disconnectIn: 10}
command: "test_command",
data: { disconnectIn: 10 },
})
.catch(ignoreWebSocketDisconnect)
.catch(ignoreWebSocketDisconnect);
}
let connectsCount = 0
let disconnectsCount = 0
let reconnectsCount = 0
let code = 0
this.client.connection.on('reconnecting', () => {
reconnectsCount += 1
})
this.client.connection.on('disconnected', (_code) => {
code = _code
disconnectsCount += 1
})
const num = 3
this.client.connection.on('connected', () => {
connectsCount += 1
let connectsCount = 0;
let disconnectsCount = 0;
let reconnectsCount = 0;
let code = 0;
this.client.connection.on("reconnecting", () => {
reconnectsCount += 1;
});
this.client.connection.on("disconnected", (_code) => {
code = _code;
disconnectsCount += 1;
});
const num = 3;
this.client.connection.on("connected", () => {
connectsCount += 1;
if (connectsCount < num) {
breakConnection()
breakConnection();
}
if (connectsCount === num) {
if (disconnectsCount !== num) {
done(
new Error(
'disconnectsCount must be equal to ' +
num +
'(got ' +
disconnectsCount +
' instead)'
`disconnectsCount must be equal to ${num}(got ${disconnectsCount} instead)`
)
)
);
} else if (reconnectsCount !== num) {
done(
new Error(
'reconnectsCount must be equal to ' +
num +
' (got ' +
reconnectsCount +
' instead)'
`reconnectsCount must be equal to ${num} (got ${reconnectsCount} instead)`
)
)
);
} else if (code !== 1006) {
done(
new Error(
'disconnect must send code 1006 (got ' + code + ' instead)'
)
)
new Error(`disconnect must send code 1006 (got ${code} instead)`)
);
} else {
done()
done();
}
}
})
});
breakConnection()
})
})
breakConnection();
});
});
it('reconnect event on heartbeat failure', function (done) {
it("reconnect event on heartbeat failure", function (done) {
if (isBrowser) {
const phantomTest = /PhantomJS/
if (phantomTest.test(navigator.userAgent)) {
if (navigator.userAgent.includes("PhantomJS")) {
// inside PhantomJS this one just hangs, so skip as not very relevant
done()
return
done();
return;
}
}
// Set the heartbeat to less than the 1 second ping response
this.client.connection._config.timeout = 500
this.client.connection._config.timeout = 500;
// Drop the test runner timeout, since this should be a quick test
this.timeout(5000)
this.timeout(5000);
// Hook up a listener for the reconnect event
this.client.connection.on('reconnect', () => done())
this.client.connection.on("reconnect", () => done());
// Trigger a heartbeat
this.client.connection._heartbeat().catch((error) => {
/* ignore - test expects heartbeat failure */
})
})
});
});
it('heartbeat failure and reconnect failure', function (done) {
it("heartbeat failure and reconnect failure", function (done) {
if (isBrowser) {
const phantomTest = /PhantomJS/
if (phantomTest.test(navigator.userAgent)) {
if (navigator.userAgent.includes("PhantomJS")) {
// inside PhantomJS this one just hangs, so skip as not very relevant
done()
return
done();
return;
}
}
// Set the heartbeat to less than the 1 second ping response
this.client.connection._config.timeout = 500
this.client.connection._config.timeout = 500;
// Drop the test runner timeout, since this should be a quick test
this.timeout(5000)
this.timeout(5000);
// fail on reconnect/connection
this.client.connection.reconnect = async () => {
throw new Error('error on reconnect')
}
throw new Error("error on reconnect");
};
// Hook up a listener for the reconnect error event
this.client.on('error', (error, message) => {
if (error === 'reconnect' && message === 'error on reconnect') {
return done()
this.client.on("error", (error, message) => {
if (error === "reconnect" && message === "error on reconnect") {
return done();
}
return done(new Error('Expected error on reconnect'))
})
return done(new Error("Expected error on reconnect"));
});
// Trigger a heartbeat
this.client.connection._heartbeat()
})
this.client.connection._heartbeat();
});
it('should emit disconnected event with code 1000 (CLOSE_NORMAL)', function (done) {
this.client.once('disconnected', (code) => {
assert.strictEqual(code, 1000)
done()
})
this.client.disconnect()
})
it("should emit disconnected event with code 1000 (CLOSE_NORMAL)", function (done) {
this.client.once("disconnected", (code) => {
assert.strictEqual(code, 1000);
done();
});
this.client.disconnect();
});
it('should emit disconnected event with code 1006 (CLOSE_ABNORMAL)', function (done) {
this.client.connection.once('error', (error) => {
done(new Error('should not throw error, got ' + String(error)))
})
this.client.connection.once('disconnected', (code) => {
assert.strictEqual(code, 1006)
done()
})
it("should emit disconnected event with code 1006 (CLOSE_ABNORMAL)", function (done) {
this.client.connection.once("error", (error) => {
done(new Error(`should not throw error, got ${String(error)}`));
});
this.client.connection.once("disconnected", (code) => {
assert.strictEqual(code, 1006);
done();
});
this.client.connection
.request({
command: 'test_command',
data: {disconnectIn: 10}
command: "test_command",
data: { disconnectIn: 10 },
})
.catch(ignoreWebSocketDisconnect)
})
.catch(ignoreWebSocketDisconnect);
});
it('should emit connected event on after reconnect', function (done) {
this.client.once('connected', done)
this.client.connection._ws.close()
})
it("should emit connected event on after reconnect", function (done) {
this.client.once("connected", done);
this.client.connection._ws.close();
});
it('Multiply connect calls', function () {
it("Multiply connect calls", function () {
return this.client.connect().then(() => {
return this.client.connect()
})
})
return this.client.connect();
});
});
it('Cannot connect because no server', function () {
const connection = new Connection(undefined as string)
it("Cannot connect because no server", function () {
const connection = new Connection(undefined as unknown as string);
return connection
.connect()
.then(() => {
assert(false, 'Should throw ConnectionError')
assert(false, "Should throw ConnectionError");
})
.catch((error) => {
assert(
error instanceof this.client.errors.ConnectionError,
'Should throw ConnectionError'
)
})
})
"Should throw ConnectionError"
);
});
});
it('connect multiserver error', function () {
it("connect multiserver error", function () {
assert.throws(function () {
new Client({
servers: ['wss://server1.com', 'wss://server2.com']
} as any)
}, this.client.errors.RippleError)
})
servers: ["wss://server1.com", "wss://server2.com"],
} as any);
}, this.client.errors.RippleError);
});
it('connect throws error', function (done) {
this.client.once('error', (type, info) => {
assert.strictEqual(type, 'type')
assert.strictEqual(info, 'info')
done()
})
this.client.connection.emit('error', 'type', 'info')
})
it("connect throws error", function (done) {
this.client.once("error", (type, info) => {
assert.strictEqual(type, "type");
assert.strictEqual(info, "info");
done();
});
this.client.connection.emit("error", "type", "info");
});
it('emit stream messages', function (done) {
let transactionCount = 0
let pathFindCount = 0
this.client.connection.on('transaction', () => {
transactionCount++
})
this.client.connection.on('path_find', () => {
pathFindCount++
})
this.client.connection.on('response', (message) => {
assert.strictEqual(message.id, 1)
assert.strictEqual(transactionCount, 1)
assert.strictEqual(pathFindCount, 1)
done()
})
it("emit stream messages", function (done) {
let transactionCount = 0;
let pathFindCount = 0;
this.client.connection.on("transaction", () => {
transactionCount++;
});
this.client.connection.on("path_find", () => {
pathFindCount++;
});
this.client.connection.on("response", (message) => {
assert.strictEqual(message.id, 1);
assert.strictEqual(transactionCount, 1);
assert.strictEqual(pathFindCount, 1);
done();
});
this.client.connection._onMessage(
JSON.stringify({
type: 'transaction'
type: "transaction",
})
)
);
this.client.connection._onMessage(
JSON.stringify({
type: 'path_find'
type: "path_find",
})
)
);
this.client.connection._onMessage(
JSON.stringify({
type: 'response',
id: 1
type: "response",
id: 1,
})
)
})
);
});
it('invalid message id', function (done) {
this.client.on('error', (errorCode, errorMessage, message) => {
assert.strictEqual(errorCode, 'badMessage')
assert.strictEqual(errorMessage, 'valid id not found in response')
assert.strictEqual(message, '{"type":"response","id":"must be integer"}')
done()
})
it("invalid message id", function (done) {
this.client.on("error", (errorCode, errorMessage, message) => {
assert.strictEqual(errorCode, "badMessage");
assert.strictEqual(errorMessage, "valid id not found in response");
assert.strictEqual(message, '{"type":"response","id":"must be integer"}');
done();
});
this.client.connection._onMessage(
JSON.stringify({
type: 'response',
id: 'must be integer'
type: "response",
id: "must be integer",
})
)
})
);
});
it('propagates error message', function (done) {
this.client.on('error', (errorCode, errorMessage, data) => {
assert.strictEqual(errorCode, 'slowDown')
assert.strictEqual(errorMessage, 'slow down')
assert.deepEqual(data, {error: 'slowDown', error_message: 'slow down'})
done()
})
it("propagates error message", function (done) {
this.client.on("error", (errorCode, errorMessage, data) => {
assert.strictEqual(errorCode, "slowDown");
assert.strictEqual(errorMessage, "slow down");
assert.deepEqual(data, { error: "slowDown", error_message: "slow down" });
done();
});
this.client.connection._onMessage(
JSON.stringify({
error: 'slowDown',
error_message: 'slow down'
error: "slowDown",
error_message: "slow down",
})
)
})
);
});
it("propagates RippledError data", function (done) {
const request = { command: "subscribe", streams: "validations" };
this.mockRippled.addResponse(request, rippled.subscribe.error);
it('propagates RippledError data', function (done) {
const request = {command: 'subscribe', streams: 'validations'}
this.mockRippled.addResponse(request, rippled.subscribe.error)
this.client.request(request).catch((error) => {
assert.strictEqual(error.name, 'RippledError')
assert.strictEqual(error.data.error, 'invalidParams')
assert.strictEqual(error.message, 'Invalid parameters.')
assert.strictEqual(error.data.error_code, 31)
assert.strictEqual(error.data.error_message, 'Invalid parameters.')
assert.strictEqual(error.name, "RippledError");
assert.strictEqual(error.data.error, "invalidParams");
assert.strictEqual(error.message, "Invalid parameters.");
assert.strictEqual(error.data.error_code, 31);
assert.strictEqual(error.data.error_message, "Invalid parameters.");
assert.deepEqual(error.data.request, {
command: 'subscribe',
command: "subscribe",
id: 0,
streams: 'validations'
})
assert.strictEqual(error.data.status, 'error')
assert.strictEqual(error.data.type, 'response')
done()
})
})
streams: "validations",
});
done();
});
});
it('unrecognized message type', function (done) {
it("unrecognized message type", function (done) {
// This enables us to automatically support any
// new messages added by rippled in the future.
this.client.connection.on('unknown', (event) => {
assert.deepEqual(event, {type: 'unknown'})
done()
})
this.client.connection.on("unknown", (event) => {
assert.deepEqual(event, { type: "unknown" });
done();
});
this.client.connection._onMessage(JSON.stringify({type: 'unknown'}))
})
this.client.connection._onMessage(JSON.stringify({ type: "unknown" }));
});
// it('should clean up websocket connection if error after websocket is opened', async function () {
// await this.client.disconnect()
@@ -555,34 +543,35 @@ describe('Connection', function () {
// }
// })
it('should try to reconnect on empty subscribe response on reconnect', function (done) {
this.timeout(23000)
this.client.on('error', (error) => {
done(error || new Error('Should not emit error.'))
})
let disconnectedCount = 0
this.client.on('connected', () => {
it("should try to reconnect on empty subscribe response on reconnect", function (done) {
this.timeout(23000);
this.client.on("error", (error) => {
done(error || new Error("Should not emit error."));
});
let disconnectedCount = 0;
this.client.on("connected", () => {
done(
disconnectedCount !== 1
? new Error('Wrong number of disconnects')
? new Error("Wrong number of disconnects")
: undefined
)
})
this.client.on('disconnected', () => {
disconnectedCount++
})
);
});
this.client.on("disconnected", () => {
disconnectedCount++;
});
this.client.connection.request({
command: 'test_command',
data: {disconnectIn: 5}
})
})
command: "test_command",
data: { disconnectIn: 5 },
});
});
it('should not crash on error', async function (done) {
this.mockRippled.suppressOutput = true
this.client.connection.request({
command: 'test_garbage'
})
.then(() => new Error('Should not have succeeded'))
.catch(done())
})
})
it("should not crash on error", async function (done) {
this.mockRippled.suppressOutput = true;
this.client.connection
.request({
command: "test_garbage",
})
.then(() => new Error("Should not have succeeded"))
.catch(done());
});
});

View File

@@ -1,49 +1,54 @@
import _ from 'lodash'
import assert from 'assert'
import wallet from './wallet'
import requests from '../fixtures/requests'
import {Client} from 'xrpl-local'
import {payTo, ledgerAccept} from './utils'
import {errors} from 'xrpl-local/common'
import {isValidSecret} from 'xrpl-local/utils'
import { generateXAddress } from '../../src/utils/generateAddress'
import { isValidXAddress } from 'ripple-address-codec'
import assert from "assert";
import _ from "lodash";
import { isValidXAddress } from "ripple-address-codec";
import { Client } from "xrpl-local";
import { errors } from "xrpl-local/common";
import { isValidSecret } from "xrpl-local/utils";
import { generateXAddress } from "../../src/utils/generateAddress";
import requests from "../fixtures/requests";
import { payTo, ledgerAccept } from "./utils";
import wallet from "./wallet";
// how long before each test case times out
const TIMEOUT = 20000
const INTERVAL = 1000 // how long to wait between checks for validated ledger
const TIMEOUT = 20000;
const INTERVAL = 1000; // how long to wait between checks for validated ledger
const HOST = process.env.HOST ?? "0.0.0.0"
const PORT = process.env.PORT ?? "6006"
const serverUrl = `ws://${HOST}:${PORT}`
const HOST = process.env.HOST ?? "0.0.0.0";
const PORT = process.env.PORT ?? "6006";
const serverUrl = `ws://${HOST}:${PORT}`;
console.log(serverUrl)
console.log(serverUrl);
function acceptLedger(client) {
return client.connection.request({command: 'ledger_accept'})
return client.connection.request({ command: "ledger_accept" });
}
function verifyTransaction(testcase, hash, type, options, txData, account) {
console.log('VERIFY...')
console.log("VERIFY...");
return testcase.client
.request({
command: 'tx',
command: "tx",
transaction: hash,
min_ledger: options.minLedgerVersion,
max_ledger: options.maxLedgerVersion
}).then((data) => {
assert(data && data.result)
assert.strictEqual(data.result.TransactionType, type)
assert.strictEqual(data.result.Account, account)
assert.strictEqual(data.result.meta.TransactionResult, 'tesSUCCESS')
max_ledger: options.maxLedgerVersion,
})
.then((data) => {
assert(data && data.result);
assert.strictEqual(data.result.TransactionType, type);
assert.strictEqual(data.result.Account, account);
assert.strictEqual(data.result.meta.TransactionResult, "tesSUCCESS");
if (testcase.transactions != null) {
testcase.transactions.push(hash)
testcase.transactions.push(hash);
}
return {txJSON: JSON.stringify(txData), id: hash, tx: data}
return { txJSON: JSON.stringify(txData), id: hash, tx: data };
})
.catch((error) => {
if (error instanceof errors.PendingLedgerVersionError) {
console.log('NOT VALIDATED YET...')
console.log("NOT VALIDATED YET...");
return new Promise((resolve, reject) => {
setTimeout(
() =>
@@ -56,12 +61,12 @@ function verifyTransaction(testcase, hash, type, options, txData, account) {
account
).then(resolve, reject),
INTERVAL
)
})
);
});
}
console.log(error.stack)
assert(false, 'Transaction not successful: ' + error.message)
})
console.log(error.stack);
assert(false, `Transaction not successful: ${error.message}`);
});
}
function testTransaction(
@@ -72,27 +77,27 @@ function testTransaction(
address = wallet.getAddress(),
secret = wallet.getSecret()
) {
const txJSON = prepared.txJSON
assert(txJSON, 'missing txJSON')
const txData = JSON.parse(txJSON)
assert.strictEqual(txData.Account, address)
const signedData = testcase.client.sign(txJSON, secret)
console.log('PREPARED...')
const txJSON = prepared.txJSON;
assert(txJSON, "missing txJSON");
const txData = JSON.parse(txJSON);
assert.strictEqual(txData.Account, address);
const signedData = testcase.client.sign(txJSON, secret);
console.log("PREPARED...");
return testcase.client
.request({command: 'submit', tx_blob: signedData.signedTransaction})
.request({ command: "submit", tx_blob: signedData.signedTransaction })
.then((response) =>
testcase.test.title.indexOf('multisign') !== -1
testcase.test.title.indexOf("multisign") !== -1
? acceptLedger(testcase.client).then(() => response)
: response
)
.then((response) => {
console.log('SUBMITTED...')
assert.strictEqual(response.result.engine_result, 'tesSUCCESS')
console.log("SUBMITTED...");
assert.strictEqual(response.result.engine_result, "tesSUCCESS");
const options = {
minLedgerVersion: lastClosedLedgerVersion,
maxLedgerVersion: txData.LastLedgerSequence
}
ledgerAccept(testcase.client)
maxLedgerVersion: txData.LastLedgerSequence,
};
ledgerAccept(testcase.client);
return new Promise((resolve, reject) => {
setTimeout(
() =>
@@ -105,71 +110,81 @@ function testTransaction(
address
).then(resolve, reject),
INTERVAL
)
})
})
);
});
});
}
function setup(this: any, server = serverUrl) {
this.client = new Client(server)
console.log('CONNECTING...')
this.client = new Client(server);
console.log("CONNECTING...");
return this.client.connect().then(
() => {
console.log('CONNECTED...')
console.log("CONNECTED...");
},
(error) => {
console.log('ERROR:', error)
throw error
console.log("ERROR:", error);
throw error;
}
)
);
}
const masterAccount = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
const masterSecret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb'
const masterAccount = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
const masterSecret = "snoPBrXtMeMyMHUVTgbuqAfg1SUTb";
function makeTrustLine(testcase, address, secret) {
const client = testcase.client
const client = testcase.client;
const specification = {
currency: 'USD',
currency: "USD",
counterparty: masterAccount,
limit: '1341.1',
ripplingDisabled: true
}
limit: "1341.1",
ripplingDisabled: true,
};
const trust = client
.prepareTrustline(address, specification, {})
.then((data) => {
const signed = client.sign(data.txJSON, secret)
const signed = client.sign(data.txJSON, secret);
if (address === wallet.getAddress()) {
testcase.transactions.push(signed.id)
testcase.transactions.push(signed.id);
}
return client.request({command: 'submit', tx_blob: signed.signedTransaction})
return client.request({
command: "submit",
tx_blob: signed.signedTransaction,
});
})
.then(() => ledgerAccept(client))
return trust
.then(() => ledgerAccept(client));
return trust;
}
function makeOrder(client, address, specification, secret) {
return client
.prepareOrder(address, specification)
.then((data) => client.sign(data.txJSON, secret))
.then((signed) => client.request({command: 'submit', tx_blob: signed.signedTransaction}))
.then(() => ledgerAccept(client))
.then((signed) =>
client.request({ command: "submit", tx_blob: signed.signedTransaction })
)
.then(() => ledgerAccept(client));
}
function setupAccounts(testcase) {
const client = testcase.client
const client = testcase.client;
const promise = payTo(client, 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM')
const promise = payTo(client, "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM")
.then(() => payTo(client, wallet.getAddress()))
.then(() => payTo(client, testcase.newWallet.xAddress))
.then(() => payTo(client, 'rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc'))
.then(() => payTo(client, 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q'))
.then(() => payTo(client, "rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc"))
.then(() => payTo(client, "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"))
.then(() => {
return client
.prepareSettings(masterAccount, {defaultRipple: true})
.prepareSettings(masterAccount, { defaultRipple: true })
.then((data) => client.sign(data.txJSON, masterSecret))
.then((signed) => client.request({command: 'submit', tx_blob: signed.signedTransaction}))
.then(() => ledgerAccept(client))
.then((signed) =>
client.request({
command: "submit",
tx_blob: signed.signedTransaction,
})
)
.then(() => ledgerAccept(client));
})
.then(() =>
makeTrustLine(testcase, wallet.getAddress(), wallet.getSecret())
@@ -181,57 +196,57 @@ function setupAccounts(testcase) {
testcase.newWallet.secret
)
)
.then(() => payTo(client, wallet.getAddress(), '123', 'USD', masterAccount))
.then(() => payTo(client, 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q'))
.then(() => payTo(client, wallet.getAddress(), "123", "USD", masterAccount))
.then(() => payTo(client, "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"))
.then(() => {
const orderSpecification = {
direction: 'buy',
direction: "buy",
quantity: {
currency: 'USD',
value: '432',
counterparty: masterAccount
currency: "USD",
value: "432",
counterparty: masterAccount,
},
totalPrice: {
currency: 'XRP',
value: '432'
}
}
currency: "XRP",
value: "432",
},
};
return makeOrder(
testcase.client,
testcase.newWallet.xAddress,
orderSpecification,
testcase.newWallet.secret
)
);
})
.then(() => {
const orderSpecification = {
direction: 'buy',
direction: "buy",
quantity: {
currency: 'XRP',
value: '1741'
currency: "XRP",
value: "1741",
},
totalPrice: {
currency: 'USD',
value: '171',
counterparty: masterAccount
}
}
currency: "USD",
value: "171",
counterparty: masterAccount,
},
};
return makeOrder(
testcase.client,
masterAccount,
orderSpecification,
masterSecret
)
})
return promise
);
});
return promise;
}
function teardown(this: any) {
return this.client.disconnect()
return this.client.disconnect();
}
function suiteSetup(this: any) {
this.transactions = []
this.transactions = [];
return (
setup
@@ -241,208 +256,209 @@ function suiteSetup(this: any) {
// two times to give time to server to send `ledgerClosed` event
// so getLedgerVersion will return right value
.then(() => ledgerAccept(this.client))
.then(() => this.client.request({
command: 'ledger',
ledger_index: 'validated'
})
.then(response => response.result.ledger_index))
.then(() =>
this.client
.request({
command: "ledger",
ledger_index: "validated",
})
.then((response) => response.result.ledger_index)
)
.then((ledgerVersion) => {
this.startLedgerVersion = ledgerVersion
this.startLedgerVersion = ledgerVersion;
})
.then(() => setupAccounts(this))
.then(() => teardown.bind(this)())
)
);
}
describe('integration tests', function () {
const address = wallet.getAddress()
const instructions = {maxLedgerVersionOffset: 10}
this.timeout(TIMEOUT)
describe("integration tests", function () {
const address = wallet.getAddress();
const instructions = { maxLedgerVersionOffset: 10 };
this.timeout(TIMEOUT);
before(suiteSetup)
beforeEach(_.partial(setup, serverUrl))
afterEach(teardown)
before(suiteSetup);
beforeEach(_.partial(setup, serverUrl));
afterEach(teardown);
it('trustline', function () {
return this.client.request({
command: 'ledger',
ledger_index: 'validated'
})
.then(response => response.result.ledger_index)
.then((ledgerVersion) => {
return this.client
.prepareTrustline(
address,
requests.prepareTrustline.simple,
instructions
)
.then((prepared) =>
testTransaction(this, 'TrustSet', ledgerVersion, prepared)
)
})
})
it("trustline", function () {
return this.client
.request({
command: "ledger",
ledger_index: "validated",
})
.then((response) => response.result.ledger_index)
.then((ledgerVersion) => {
return this.client
.prepareTrustline(
address,
requests.prepareTrustline.simple,
instructions
)
.then((prepared) =>
testTransaction(this, "TrustSet", ledgerVersion, prepared)
);
});
});
it('payment', function () {
const amount = {currency: 'XRP', value: '0.000001'}
it("payment", function () {
const amount = { currency: "XRP", value: "0.000001" };
const paymentSpecification = {
source: {
address: address,
maxAmount: amount
address,
maxAmount: amount,
},
destination: {
address: 'rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc',
amount: amount
}
}
return this.client.request({
command: 'ledger',
ledger_index: 'validated'
})
.then(response => response.result.ledger_index)
.then((ledgerVersion) => {
return this.client
.preparePayment(address, paymentSpecification, instructions)
.then((prepared) =>
testTransaction(this, 'Payment', ledgerVersion, prepared)
)
})
})
address: "rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc",
amount,
},
};
return this.client
.request({
command: "ledger",
ledger_index: "validated",
})
.then((response) => response.result.ledger_index)
.then((ledgerVersion) => {
return this.client
.preparePayment(address, paymentSpecification, instructions)
.then((prepared) =>
testTransaction(this, "Payment", ledgerVersion, prepared)
);
});
});
it('order', function () {
it("order", function () {
const orderSpecification = {
direction: 'buy',
direction: "buy",
quantity: {
currency: 'USD',
value: '237',
counterparty: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q'
currency: "USD",
value: "237",
counterparty: "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
},
totalPrice: {
currency: 'XRP',
value: '0.0002'
}
}
currency: "XRP",
value: "0.0002",
},
};
const expectedOrder = {
flags: 0,
quality: "1.185",
taker_gets: '200',
taker_gets: "200",
taker_pays: {
currency: 'USD',
value: '237',
issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q'
}
}
return this.client.request({
command: 'ledger',
ledger_index: 'validated'
})
.then(response => response.result.ledger_index)
.then((ledgerVersion) => {
return this.client
.prepareOrder(address, orderSpecification, instructions)
.then((prepared) =>
testTransaction(this, 'OfferCreate', ledgerVersion, prepared)
)
.then((result) => {
const txData = JSON.parse(result.txJSON)
return this.client.request({
command: 'account_offers',
account: address
}).then(response => response.result.offers)
.then((orders) => {
assert(orders && orders.length > 0)
const createdOrder = (
orders.filter((order) => {
return order.seq === txData.Sequence
currency: "USD",
value: "237",
issuer: "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
},
};
return this.client
.request({
command: "ledger",
ledger_index: "validated",
})
.then((response) => response.result.ledger_index)
.then((ledgerVersion) => {
return this.client
.prepareOrder(address, orderSpecification, instructions)
.then((prepared) =>
testTransaction(this, "OfferCreate", ledgerVersion, prepared)
)
.then((result) => {
const txData = JSON.parse(result.txJSON);
return this.client
.request({
command: "account_offers",
account: address,
})
)[0]
assert(createdOrder)
delete createdOrder.seq
assert.deepEqual(createdOrder, expectedOrder)
return txData
.then((response) => response.result.offers)
.then((orders) => {
assert(orders && orders.length > 0);
const createdOrder = orders.filter((order) => {
return order.seq === txData.Sequence;
})[0];
assert(createdOrder);
delete createdOrder.seq;
assert.deepEqual(createdOrder, expectedOrder);
return txData;
});
})
})
.then((txData) =>
this.client
.prepareOrderCancellation(
address,
{orderSequence: txData.Sequence},
instructions
)
.then((prepared) =>
testTransaction(
this,
'OfferCancel',
ledgerVersion,
prepared
.then((txData) =>
this.client
.prepareOrderCancellation(
address,
{ orderSequence: txData.Sequence },
instructions
)
)
)
})
})
.then((prepared) =>
testTransaction(this, "OfferCancel", ledgerVersion, prepared)
)
);
});
});
it('isConnected', function () {
assert(this.client.isConnected())
})
it("isConnected", function () {
assert(this.client.isConnected());
});
it('getFee', function () {
it("getFee", function () {
return this.client.getFee().then((fee) => {
assert.strictEqual(typeof fee, 'string')
assert(!isNaN(Number(fee)))
assert(parseFloat(fee) === Number(fee))
})
})
assert.strictEqual(typeof fee, "string");
assert(!isNaN(Number(fee)));
assert(parseFloat(fee) === Number(fee));
});
});
it('getTrustlines', function () {
const fixture = requests.prepareTrustline.simple
const { currency, counterparty } = fixture
const options = { currency, counterparty }
it("getTrustlines", function () {
const fixture = requests.prepareTrustline.simple;
const { currency, counterparty } = fixture;
const options = { currency, counterparty };
return this.client.getTrustlines(address, options).then((data) => {
assert(data && data.length > 0 && data[0] && data[0].specification)
const specification = data[0].specification
assert.strictEqual(Number(specification.limit), Number(fixture.limit))
assert.strictEqual(specification.currency, fixture.currency)
assert.strictEqual(specification.counterparty, fixture.counterparty)
})
})
assert(data && data.length > 0 && data[0] && data[0].specification);
const specification = data[0].specification;
assert.strictEqual(Number(specification.limit), Number(fixture.limit));
assert.strictEqual(specification.currency, fixture.currency);
assert.strictEqual(specification.counterparty, fixture.counterparty);
});
});
it('getBalances', function () {
const fixture = requests.prepareTrustline.simple
const { currency, counterparty } = fixture
const options = { currency, counterparty }
it("getBalances", function () {
const fixture = requests.prepareTrustline.simple;
const { currency, counterparty } = fixture;
const options = { currency, counterparty };
return this.client.getBalances(address, options).then((data) => {
assert(data && data.length > 0 && data[0])
assert.strictEqual(data[0].currency, fixture.currency)
assert.strictEqual(data[0].counterparty, fixture.counterparty)
})
})
assert(data && data.length > 0 && data[0]);
assert.strictEqual(data[0].currency, fixture.currency);
assert.strictEqual(data[0].counterparty, fixture.counterparty);
});
});
it('getOrderbook', function () {
it("getOrderbook", function () {
const orderbook = {
base: {
currency: 'XRP'
currency: "XRP",
},
counter: {
currency: 'USD',
counterparty: masterAccount
}
}
currency: "USD",
counterparty: masterAccount,
},
};
return this.client.getOrderbook(address, orderbook).then((book) => {
assert(book && book.bids && book.bids.length > 0)
assert(book.asks && book.asks.length > 0)
const bid = book.bids[0]
assert(bid && bid.specification && bid.specification.quantity)
assert(bid.specification.totalPrice)
assert.strictEqual(bid.specification.direction, 'buy')
assert.strictEqual(bid.specification.quantity.currency, 'XRP')
assert.strictEqual(bid.specification.totalPrice.currency, 'USD')
const ask = book.asks[0]
assert(ask && ask.specification && ask.specification.quantity)
assert(ask.specification.totalPrice)
assert.strictEqual(ask.specification.direction, 'sell')
assert.strictEqual(ask.specification.quantity.currency, 'XRP')
assert.strictEqual(ask.specification.totalPrice.currency, 'USD')
})
})
assert(book && book.bids && book.bids.length > 0);
assert(book.asks && book.asks.length > 0);
const bid = book.bids[0];
assert(bid && bid.specification && bid.specification.quantity);
assert(bid.specification.totalPrice);
assert.strictEqual(bid.specification.direction, "buy");
assert.strictEqual(bid.specification.quantity.currency, "XRP");
assert.strictEqual(bid.specification.totalPrice.currency, "USD");
const ask = book.asks[0];
assert(ask && ask.specification && ask.specification.quantity);
assert(ask.specification.totalPrice);
assert.strictEqual(ask.specification.direction, "sell");
assert.strictEqual(ask.specification.quantity.currency, "XRP");
assert.strictEqual(ask.specification.totalPrice.currency, "USD");
});
});
// it('getPaths', function () {
// const pathfind = {
@@ -501,100 +517,104 @@ describe('integration tests', function () {
// })
// })
it('generateWallet', function () {
const newWallet = generateXAddress()
assert(newWallet && newWallet.xAddress && newWallet.secret)
assert(isValidXAddress(newWallet.xAddress))
assert(isValidSecret(newWallet.secret))
})
})
it("generateWallet", function () {
const newWallet = generateXAddress();
assert(newWallet && newWallet.xAddress && newWallet.secret);
assert(isValidXAddress(newWallet.xAddress));
assert(isValidSecret(newWallet.secret));
});
});
describe('integration tests - standalone rippled', function () {
const instructions = {maxLedgerVersionOffset: 10}
this.timeout(TIMEOUT)
describe("integration tests - standalone rippled", function () {
const instructions = { maxLedgerVersionOffset: 10 };
this.timeout(TIMEOUT);
beforeEach(_.partial(setup, serverUrl))
afterEach(teardown)
const address = 'r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs'
const secret = 'ss6F8381Br6wwpy9p582H8sBt19J3'
const signer1address = 'rQDhz2ZNXmhxzCYwxU6qAbdxsHA4HV45Y2'
const signer1secret = 'shK6YXzwYfnFVn3YZSaMh5zuAddKx'
const signer2address = 'r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud'
const signer2secret = 'shUHQnL4EH27V4EiBrj6EfhWvZngF'
beforeEach(_.partial(setup, serverUrl));
afterEach(teardown);
const address = "r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs";
const secret = "ss6F8381Br6wwpy9p582H8sBt19J3";
const signer1address = "rQDhz2ZNXmhxzCYwxU6qAbdxsHA4HV45Y2";
const signer1secret = "shK6YXzwYfnFVn3YZSaMh5zuAddKx";
const signer2address = "r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud";
const signer2secret = "shUHQnL4EH27V4EiBrj6EfhWvZngF";
it('submit multisigned transaction', function () {
it("submit multisigned transaction", function () {
const signers = {
threshold: 2,
weights: [
{address: signer1address, weight: 1},
{address: signer2address, weight: 1}
]
}
let minLedgerVersion = null
{ address: signer1address, weight: 1 },
{ address: signer2address, weight: 1 },
],
};
let minLedgerVersion = null;
return payTo(this.client, address)
.then(() => {
return this.client.request({
command: 'ledger',
ledger_index: 'validated'
})
.then(response => response.result.ledger_index)
.then((ledgerVersion) => {
minLedgerVersion = ledgerVersion
return this.client
.prepareSettings(address, {signers}, instructions)
.then((prepared) => {
return testTransaction(
this,
'SignerListSet',
ledgerVersion,
prepared,
address,
secret
)
})
})
return this.client
.request({
command: "ledger",
ledger_index: "validated",
})
.then((response) => response.result.ledger_index)
.then((ledgerVersion) => {
minLedgerVersion = ledgerVersion;
return this.client
.prepareSettings(address, { signers }, instructions)
.then((prepared) => {
return testTransaction(
this,
"SignerListSet",
ledgerVersion,
prepared,
address,
secret
);
});
});
})
.then(() => {
const multisignInstructions = Object.assign({}, instructions, {
signersCount: 2
})
const multisignInstructions = { ...instructions, signersCount: 2 };
return this.client
.prepareSettings(
address,
{domain: 'example.com'},
{ domain: "example.com" },
multisignInstructions
)
.then((prepared) => {
const signed1 = this.client.sign(prepared.txJSON, signer1secret, {
signAs: signer1address
})
signAs: signer1address,
});
const signed2 = this.client.sign(prepared.txJSON, signer2secret, {
signAs: signer2address
})
signAs: signer2address,
});
const combined = this.client.combine([
signed1.signedTransaction,
signed2.signedTransaction
])
signed2.signedTransaction,
]);
return this.client
.request({command: 'submit', tx_blob: combined.signedTransaction})
.then((response) => acceptLedger(this.client).then(() => response))
.request({
command: "submit",
tx_blob: combined.signedTransaction,
})
.then((response) =>
acceptLedger(this.client).then(() => response)
)
.then((response) => {
assert.strictEqual(response.result.engine_result, 'tesSUCCESS')
const options = {minLedgerVersion}
assert.strictEqual(response.result.engine_result, "tesSUCCESS");
const options = { minLedgerVersion };
return verifyTransaction(
this,
combined.id,
'AccountSet',
"AccountSet",
options,
{},
address
)
);
})
.catch((error) => {
console.log(error.message)
throw error
})
})
})
})
})
console.log(error.message);
throw error;
});
});
});
});
});

View File

@@ -1,17 +1,18 @@
import _ from 'lodash'
import {Server as WebSocketServer} from 'ws'
import {EventEmitter2} from 'eventemitter2'
import {getFreePort} from './testUtils'
import { Request } from '../src'
import { EventEmitter2 } from "eventemitter2";
import _ from "lodash";
import { Server as WebSocketServer } from "ws";
import type { Request } from "../src";
import { getFreePort } from "./testUtils";
function createResponse(request, response, overrides = {}) {
const result = Object.assign({}, response.result, overrides)
const result = { ...response.result, ...overrides };
const change =
response.result && !_.isEmpty(overrides)
? {id: request.id, result: result}
: {id: request.id}
return JSON.stringify(Object.assign({}, response, change))
? { id: request.id, result }
: { id: request.id };
return JSON.stringify({ ...response, ...change });
}
function ping(conn, request) {
@@ -19,105 +20,111 @@ function ping(conn, request) {
conn.send(
createResponse(request, {
result: {},
status: 'success',
type: 'response'
status: "success",
type: "response",
})
)
}, 1000 * 2)
);
}, 1000 * 2);
}
// We mock out WebSocketServer in these tests and add a lot of custom
// properties not defined on the normal WebSocketServer object.
type MockedWebSocketServer = any
type MockedWebSocketServer = any;
export function createMockRippled(port) {
const mock = new WebSocketServer({port: port}) as MockedWebSocketServer
Object.assign(mock, EventEmitter2.prototype)
const mock = new WebSocketServer({ port }) as MockedWebSocketServer;
Object.assign(mock, EventEmitter2.prototype);
mock.responses = {}
mock.suppressOutput = false
mock.responses = {};
mock.suppressOutput = false;
mock.on('connection', function (this: MockedWebSocketServer, conn: any) {
this.socket = conn
conn.on('message', function (requestJSON) {
mock.on("connection", function (this: MockedWebSocketServer, conn: any) {
this.socket = conn;
conn.on("message", function (requestJSON) {
try {
const request = JSON.parse(requestJSON)
if (request.command === 'ping') {
ping(conn, request)
} else if (request.command === 'test_command') {
mock.testCommand(conn, request)
}else if (request.command in mock.responses) {
conn.send(createResponse(request, mock.getResponse(request)))
const request = JSON.parse(requestJSON);
if (request.command === "ping") {
ping(conn, request);
} else if (request.command === "test_command") {
mock.testCommand(conn, request);
} else if (request.command in mock.responses) {
conn.send(createResponse(request, mock.getResponse(request)));
} else {
throw new Error(`No event handler registered in mock rippled for ${request.command}`)
throw new Error(
`No event handler registered in mock rippled for ${request.command}`
);
}
} catch (err) {
if (!mock.suppressOutput)
console.error('Error: ' + err.message)
conn.close(4000, err.message)
if (!mock.suppressOutput) {
console.error(`Error: ${err.message}`);
}
conn.close(4000, err.message);
}
})
})
});
});
// Adds a mocked response
// If an object is passed in for `response`, then the response is static for the command
// If a function is passed in for `response`, then the response can be determined by the exact request shape
mock.addResponse = (request: Request, response: object | ((r: Request) => object)) => {
const command = request.command
mock.responses[command] = response
}
mock.addResponse = (
request: Request,
response: object | ((r: Request) => object)
) => {
const command = request.command;
mock.responses[command] = response;
};
mock.getResponse = (request: Request) : object => {
mock.getResponse = (request: Request): object => {
if (!(request.command in mock.responses)) {
throw new Error(`No handler for ${request.command}`)
throw new Error(`No handler for ${request.command}`);
}
const functionOrObject = mock.responses[request.command]
if (typeof functionOrObject === 'function') {
return functionOrObject(request)
const functionOrObject = mock.responses[request.command];
if (typeof functionOrObject === "function") {
return functionOrObject(request);
}
return functionOrObject
}
return functionOrObject;
};
mock.testCommand = function testCommand(conn, request) {
if (request.data.disconnectIn) {
setTimeout(conn.terminate.bind(conn), request.data.disconnectIn)
setTimeout(conn.terminate.bind(conn), request.data.disconnectIn);
conn.send(
createResponse(request, {
status: 'success',
type: 'response',
result: {}
status: "success",
type: "response",
result: {},
})
)
);
} else if (request.data.openOnOtherPort) {
getFreePort().then((newPort) => {
createMockRippled(newPort)
createMockRippled(newPort);
conn.send(
createResponse(request, {
status: 'success',
type: 'response',
result: {port: newPort}
status: "success",
type: "response",
result: { port: newPort },
})
)
})
);
});
} else if (request.data.closeServerAndReopen) {
setTimeout(() => {
conn.terminate()
conn.terminate();
mock.close.call(mock, () => {
setTimeout(() => {
createMockRippled(port)
}, request.data.closeServerAndReopen)
})
}, 10)
createMockRippled(port);
}, request.data.closeServerAndReopen);
});
}, 10);
} else if (request.data.unrecognizedResponse) {
conn.send(
createResponse(request, {
status: 'unrecognized',
type: 'response',
result: {}
status: "unrecognized",
type: "response",
result: {},
})
)
);
}
}
};
return mock
return mock;
}

View File

@@ -1,15 +1,17 @@
const port = 34371
import {createMockRippled} from './mockRippled'
import { createMockRippled } from "./mockRippled";
const port = 34371;
function main() {
// @ts-expect-error -- mocha.
if (global.describe) {
// we are running inside mocha, exiting
return
return;
}
console.log('starting server on port ' + port)
createMockRippled(port)
console.log('starting server on port ' + String(port + 1))
createMockRippled(port + 1)
console.log(`starting server on port ${port}`);
createMockRippled(port);
console.log(`starting server on port ${String(port + 1)}`);
createMockRippled(port + 1);
}
main()
main();

View File

@@ -1,78 +1,77 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyAccountDelete } from './../../src/models/transactions/accountDelete'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyAccountDelete } from "../../src/models/transactions/accountDelete";
/**
* AccountDelete Transaction Verification Testing
* AccountDelete Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('AccountDelete Transaction Verification', function () {
it (`verifies valid AccountDelete`, () => {
const validAccountDelete = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
DestinationTag: 13,
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648
} as any
assert.doesNotThrow(() => verifyAccountDelete(validAccountDelete))
})
describe("AccountDelete Transaction Verification", function () {
it(`verifies valid AccountDelete`, function () {
const validAccountDelete = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
DestinationTag: 13,
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648,
} as any;
assert.doesNotThrow(() => verifyAccountDelete(validAccountDelete));
});
it (`throws w/ missing Destination`, () => {
const invalidDestination = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648
} as any
it(`throws w/ missing Destination`, function () {
const invalidDestination = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648,
} as any;
assert.throws(
() => verifyAccountDelete(invalidDestination),
ValidationError,
"AccountDelete: missing field Destination"
)
})
assert.throws(
() => verifyAccountDelete(invalidDestination),
ValidationError,
"AccountDelete: missing field Destination"
);
});
it (`throws w/ invalid Destination`, () => {
const invalidDestination = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Destination: 65478965,
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648
} as any
it(`throws w/ invalid Destination`, function () {
const invalidDestination = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Destination: 65478965,
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648,
} as any;
assert.throws(
() => verifyAccountDelete(invalidDestination),
ValidationError,
"AccountDelete: invalid Destination"
)
})
assert.throws(
() => verifyAccountDelete(invalidDestination),
ValidationError,
"AccountDelete: invalid Destination"
);
});
it (`throws w/ invalid DestinationTag`, () => {
const invalidDestinationTag = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
DestinationTag: "gvftyujnbv",
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648
} as any
it(`throws w/ invalid DestinationTag`, function () {
const invalidDestinationTag = {
TransactionType: "AccountDelete",
Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
DestinationTag: "gvftyujnbv",
Fee: "5000000",
Sequence: 2470665,
Flags: 2147483648,
} as any;
assert.throws(
() => verifyAccountDelete(invalidDestinationTag),
ValidationError,
"AccountDelete: invalid DestinationTag"
)
})
})
assert.throws(
() => verifyAccountDelete(invalidDestinationTag),
ValidationError,
"AccountDelete: invalid DestinationTag"
);
});
});

View File

@@ -1,110 +1,111 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyAccountSet } from './../../src/models/transactions/accountSet'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyAccountSet } from "../../src/models/transactions/accountSet";
/**
* AccountSet Transaction Verification Testing
* AccountSet Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('AccountSet Transaction Verification', function () {
describe("AccountSet Transaction Verification", function () {
let account;
let account
beforeEach(function () {
account = {
TransactionType: "AccountSet",
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Fee: "12",
Sequence: 5,
Domain: "6578616D706C652E636F6D",
SetFlag: 5,
MessageKey:
"03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
} as any;
});
beforeEach(() => {
account = {
TransactionType : "AccountSet",
Account : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Fee : "12",
Sequence : 5,
Domain : "6578616D706C652E636F6D",
SetFlag : 5,
MessageKey : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB"
} as any
})
it(`verifies valid AccountSet`, function () {
assert.doesNotThrow(() => verifyAccountSet(account));
});
it (`verifies valid AccountSet`, () => {
assert.doesNotThrow(() => verifyAccountSet(account))
})
it(`throws w/ invalid SetFlag (out of range)`, function () {
account.SetFlag = 12;
it (`throws w/ invalid SetFlag (out of range)`, () => {
account.SetFlag = 12
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid SetFlag"
);
});
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid SetFlag"
)
})
it(`throws w/ invalid SetFlag (incorrect type)`, function () {
account.SetFlag = "abc";
it (`throws w/ invalid SetFlag (incorrect type)`, () => {
account.SetFlag = 'abc'
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid SetFlag"
)
})
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid SetFlag"
);
});
it (`throws w/ invalid ClearFlag`, () => {
account.ClearFlag = 12
it(`throws w/ invalid ClearFlag`, function () {
account.ClearFlag = 12;
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid ClearFlag"
)
})
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid ClearFlag"
);
});
it (`throws w/ invalid Domain`, () => {
account.Domain = 6578616
it(`throws w/ invalid Domain`, function () {
account.Domain = 6578616;
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid Domain"
)
})
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid Domain"
);
});
it (`throws w/ invalid EmailHash`, () => {
account.EmailHash = 657861645678909876543456789876543
it(`throws w/ invalid EmailHash`, function () {
account.EmailHash = 657861645678909876543456789876543;
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid EmailHash"
)
})
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid EmailHash"
);
});
it (`throws w/ invalid MessageKey`, () => {
account.MessageKey = 65786165678908765456789567890678
it(`throws w/ invalid MessageKey`, function () {
account.MessageKey = 65786165678908765456789567890678;
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid MessageKey"
)
})
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid MessageKey"
);
});
it (`throws w/ invalid TransferRate`, () => {
account.TransferRate = "1000000001"
it(`throws w/ invalid TransferRate`, function () {
account.TransferRate = "1000000001";
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid TransferRate"
)
})
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid TransferRate"
);
});
it (`throws w/ invalid TickSize`, () => {
account.TickSize = 20
it(`throws w/ invalid TickSize`, function () {
account.TickSize = 20;
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid TickSize"
)
})
})
assert.throws(
() => verifyAccountSet(account),
ValidationError,
"AccountSet: invalid TickSize"
);
});
});

View File

@@ -1,225 +1,232 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyBaseTransaction } from './../../src/models/transactions/common'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyBaseTransaction } from "../../src/models/transactions/common";
/**
* Transaction Verification Testing
* Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('Transaction Verification', function () {
it(`Verifies all optional BaseTransaction`, () => {
const txJson = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Fee: "12",
Sequence: 100,
AccountTxnID: "DEADBEEF",
Flags: 15,
LastLedgerSequence: 1383,
Memos: [
{
Memo: {
MemoType: "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
MemoData: "72656e74"
}
},
{
Memo: {
MemoFormat: "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
MemoData: "72656e74"
}
},
{
Memo: {
MemoType: "72656e74"
}
}
],
Signers: [
{
Account: "r....",
TxnSignature: "DEADBEEF",
SigningPubKey: "hex-string"
}
],
SourceTag: 31,
SigningPublicKey: "03680DD274EE55594F7244F489CD38CF3A5A1A4657122FB8143E185B2BA043DF36",
TicketSequence: 10,
TxnSignature: "3045022100C6708538AE5A697895937C758E99A595B57A16393F370F11B8D4C032E80B532002207776A8E85BB9FAF460A92113B9C60F170CD964196B1F084E0DAB65BAEC368B66"
}
describe("Transaction Verification", function () {
it(`Verifies all optional BaseTransaction`, function () {
const txJson = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Fee: "12",
Sequence: 100,
AccountTxnID: "DEADBEEF",
Flags: 15,
LastLedgerSequence: 1383,
Memos: [
{
Memo: {
MemoType:
"687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
MemoData: "72656e74",
},
},
{
Memo: {
MemoFormat:
"687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
MemoData: "72656e74",
},
},
{
Memo: {
MemoType: "72656e74",
},
},
],
Signers: [
{
Account: "r....",
TxnSignature: "DEADBEEF",
SigningPubKey: "hex-string",
},
],
SourceTag: 31,
SigningPublicKey:
"03680DD274EE55594F7244F489CD38CF3A5A1A4657122FB8143E185B2BA043DF36",
TicketSequence: 10,
TxnSignature:
"3045022100C6708538AE5A697895937C758E99A595B57A16393F370F11B8D4C032E80B532002207776A8E85BB9FAF460A92113B9C60F170CD964196B1F084E0DAB65BAEC368B66",
};
assert.doesNotThrow(() => verifyBaseTransaction(txJson))
})
assert.doesNotThrow(() => verifyBaseTransaction(txJson));
});
it(`Verifies only required BaseTransaction`, () => {
const txJson = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
}
assert.doesNotThrow(() => verifyBaseTransaction(txJson))
})
it(`Verifies only required BaseTransaction`, function () {
const txJson = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
};
it (`Handles invalid Fee`, () => {
const invalidFee = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Fee: 1000
} as any
assert.doesNotThrow(() => verifyBaseTransaction(txJson));
});
assert.throws(
() => verifyBaseTransaction(invalidFee),
ValidationError,
"BaseTransaction: invalid Fee"
)
})
it(`Handles invalid Fee`, function () {
const invalidFee = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Fee: 1000,
} as any;
it (`Handles invalid Sequence`, () => {
const invalidSeq = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Sequence: "145"
} as any
assert.throws(
() => verifyBaseTransaction(invalidFee),
ValidationError,
"BaseTransaction: invalid Fee"
);
});
assert.throws(
() => verifyBaseTransaction(invalidSeq),
ValidationError,
"BaseTransaction: invalid Sequence"
)
})
it(`Handles invalid Sequence`, function () {
const invalidSeq = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Sequence: "145",
} as any;
it (`Handles invalid AccountTxnID`, () => {
const invalidID = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
AccountTxnID: ["WRONG"]
} as any
assert.throws(
() => verifyBaseTransaction(invalidSeq),
ValidationError,
"BaseTransaction: invalid Sequence"
);
});
assert.throws(
() => verifyBaseTransaction(invalidID),
ValidationError,
"BaseTransaction: invalid AccountTxnID"
)
})
it(`Handles invalid AccountTxnID`, function () {
const invalidID = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
AccountTxnID: ["WRONG"],
} as any;
it (`Handles invalid LastLedgerSequence`, () => {
const invalidLastLedgerSequence = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
LastLedgerSequence: "1000"
} as any
assert.throws(
() => verifyBaseTransaction(invalidID),
ValidationError,
"BaseTransaction: invalid AccountTxnID"
);
});
assert.throws(
() => verifyBaseTransaction(invalidLastLedgerSequence),
ValidationError,
"BaseTransaction: invalid LastLedgerSequence"
)
})
it(`Handles invalid LastLedgerSequence`, function () {
const invalidLastLedgerSequence = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
LastLedgerSequence: "1000",
} as any;
it (`Handles invalid SourceTag`, () => {
const invalidSourceTag = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
SourceTag: ["ARRAY"]
} as any
assert.throws(
() => verifyBaseTransaction(invalidLastLedgerSequence),
ValidationError,
"BaseTransaction: invalid LastLedgerSequence"
);
});
assert.throws(
() => verifyBaseTransaction(invalidSourceTag),
ValidationError,
"BaseTransaction: invalid SourceTag"
)
})
it(`Handles invalid SourceTag`, function () {
const invalidSourceTag = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
SourceTag: ["ARRAY"],
} as any;
it (`Handles invalid SigningPubKey`, () => {
const invalidSigningPubKey = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
SigningPubKey: 1000
} as any
assert.throws(
() => verifyBaseTransaction(invalidSourceTag),
ValidationError,
"BaseTransaction: invalid SourceTag"
);
});
assert.throws(
() => verifyBaseTransaction(invalidSigningPubKey),
ValidationError,
"BaseTransaction: invalid SigningPubKey"
)
})
it(`Handles invalid SigningPubKey`, function () {
const invalidSigningPubKey = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
SigningPubKey: 1000,
} as any;
it (`Handles invalid TicketSequence`, () => {
const invalidTicketSequence = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
TicketSequence: "1000"
} as any
assert.throws(
() => verifyBaseTransaction(invalidSigningPubKey),
ValidationError,
"BaseTransaction: invalid SigningPubKey"
);
});
assert.throws(
() => verifyBaseTransaction(invalidTicketSequence),
ValidationError,
"BaseTransaction: invalid TicketSequence"
)
})
it(`Handles invalid TicketSequence`, function () {
const invalidTicketSequence = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
TicketSequence: "1000",
} as any;
it (`Handles invalid TxnSignature`, () => {
const invalidTxnSignature = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
TxnSignature: 1000
} as any
assert.throws(
() => verifyBaseTransaction(invalidTxnSignature),
ValidationError,
"BaseTransaction: invalid TxnSignature"
)
})
assert.throws(
() => verifyBaseTransaction(invalidTicketSequence),
ValidationError,
"BaseTransaction: invalid TicketSequence"
);
});
it (`Handles invalid Signers`, () => {
const invalidSigners = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Signers: []
} as any
it(`Handles invalid TxnSignature`, function () {
const invalidTxnSignature = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
TxnSignature: 1000,
} as any;
assert.throws(
() => verifyBaseTransaction(invalidSigners),
ValidationError,
"BaseTransaction: invalid Signers"
)
assert.throws(
() => verifyBaseTransaction(invalidTxnSignature),
ValidationError,
"BaseTransaction: invalid TxnSignature"
);
});
const invalidSigners2 = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Signers: [
{
"Account": "r...."
}
]
} as any
it(`Handles invalid Signers`, function () {
const invalidSigners = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Signers: [],
} as any;
assert.throws(
() => verifyBaseTransaction(invalidSigners2),
ValidationError,
"BaseTransaction: invalid Signers"
)
})
assert.throws(
() => verifyBaseTransaction(invalidSigners),
ValidationError,
"BaseTransaction: invalid Signers"
);
it (`Handles invalid Memo`, () => {
const invalidMemo = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Memos: [{
Memo: {
MemoData: "HI",
Address: "WRONG"
}
}]
} as any
const invalidSigners2 = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Signers: [
{
Account: "r....",
},
],
} as any;
assert.throws(
() => verifyBaseTransaction(invalidMemo),
ValidationError,
"BaseTransaction: invalid Memos"
)
})
})
assert.throws(
() => verifyBaseTransaction(invalidSigners2),
ValidationError,
"BaseTransaction: invalid Signers"
);
});
it(`Handles invalid Memo`, function () {
const invalidMemo = {
Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe",
TransactionType: "Payment",
Memos: [
{
Memo: {
MemoData: "HI",
Address: "WRONG",
},
},
],
} as any;
assert.throws(
() => verifyBaseTransaction(invalidMemo),
ValidationError,
"BaseTransaction: invalid Memos"
);
});
});

View File

@@ -1,35 +1,37 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyCheckCancel} from './../../src/models/transactions/checkCancel'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyCheckCancel } from "../../src/models/transactions/checkCancel";
/**
* CheckCancel Transaction Verification Testing
* CheckCancel Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('CheckCancel Transaction Verification', function () {
describe("CheckCancel Transaction Verification", function () {
it(`verifies valid CheckCancel`, function () {
const validCheckCancel = {
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
TransactionType: "CheckCancel",
CheckID:
"49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0",
} as any;
it (`verifies valid CheckCancel`, () => {
const validCheckCancel = {
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
TransactionType : "CheckCancel",
CheckID : "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0"
} as any
assert.doesNotThrow(() => verifyCheckCancel(validCheckCancel));
});
assert.doesNotThrow(() => verifyCheckCancel(validCheckCancel))
})
it(`throws w/ invalid CheckCancel`, function () {
const invalidCheckID = {
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
TransactionType: "CheckCancel",
CheckID: 496473456789876545678909876545678,
} as any;
it (`throws w/ invalid CheckCancel`, () => {
const invalidCheckID = {
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
TransactionType : "CheckCancel",
CheckID : 496473456789876545678909876545678
} as any
assert.throws(
() => verifyCheckCancel(invalidCheckID),
ValidationError,
"CheckCancel: invalid CheckID"
)
})
})
assert.throws(
() => verifyCheckCancel(invalidCheckID),
ValidationError,
"CheckCancel: invalid CheckID"
);
});
});

View File

@@ -1,84 +1,89 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyCheckCash } from './../../src/models/transactions/checkCash'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyCheckCash } from "../../src/models/transactions/checkCash";
/**
* CheckCash Transaction Verification Testing
* CheckCash Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('CheckCash Transaction Verification', function () {
it (`verifies valid CheckCash`, () => {
const validCheckCash = {
Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType : "CheckCash",
Amount : "100000000",
CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
Fee : "12"
} as any
assert.doesNotThrow(() => verifyCheckCash(validCheckCash))
})
describe("CheckCash Transaction Verification", function () {
it(`verifies valid CheckCash`, function () {
const validCheckCash = {
Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType: "CheckCash",
Amount: "100000000",
CheckID:
"838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
Fee: "12",
} as any;
it (`throws w/ invalid CheckID`, () => {
const invalidCheckID = {
Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType : "CheckCash",
Amount : "100000000",
CheckID : 83876645678909854567890
} as any
assert.doesNotThrow(() => verifyCheckCash(validCheckCash));
});
assert.throws(
() => verifyCheckCash(invalidCheckID),
ValidationError,
"CheckCash: invalid CheckID"
)
})
it(`throws w/ invalid CheckID`, function () {
const invalidCheckID = {
Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType: "CheckCash",
Amount: "100000000",
CheckID: 83876645678909854567890,
} as any;
it (`throws w/ invalid Amount`, () => {
const invalidAmount = {
Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType : "CheckCash",
Amount : 100000000,
CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334"
} as any
assert.throws(
() => verifyCheckCash(invalidCheckID),
ValidationError,
"CheckCash: invalid CheckID"
);
});
assert.throws(
() => verifyCheckCash(invalidAmount),
ValidationError,
"CheckCash: invalid Amount"
)
})
it(`throws w/ invalid Amount`, function () {
const invalidAmount = {
Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType: "CheckCash",
Amount: 100000000,
CheckID:
"838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
} as any;
it (`throws w/ having both Amount and DeliverMin`, () => {
const invalidDeliverMin = {
Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType : "CheckCash",
Amount : "100000000",
DeliverMin: 852156963,
CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334"
} as any
assert.throws(
() => verifyCheckCash(invalidAmount),
ValidationError,
"CheckCash: invalid Amount"
);
});
assert.throws(
() => verifyCheckCash(invalidDeliverMin),
ValidationError,
"CheckCash: cannot have both Amount and DeliverMin"
)
})
it(`throws w/ having both Amount and DeliverMin`, function () {
const invalidDeliverMin = {
Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType: "CheckCash",
Amount: "100000000",
DeliverMin: 852156963,
CheckID:
"838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
} as any;
it (`throws w/ invalid DeliverMin`, () => {
const invalidDeliverMin = {
Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType : "CheckCash",
DeliverMin: 852156963,
CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334"
} as any
assert.throws(
() => verifyCheckCash(invalidDeliverMin),
ValidationError,
"CheckCash: cannot have both Amount and DeliverMin"
);
});
assert.throws(
() => verifyCheckCash(invalidDeliverMin),
ValidationError,
"CheckCash: invalid DeliverMin"
)
})
})
it(`throws w/ invalid DeliverMin`, function () {
const invalidDeliverMin = {
Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
TransactionType: "CheckCash",
DeliverMin: 852156963,
CheckID:
"838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
} as any;
assert.throws(
() => verifyCheckCash(invalidDeliverMin),
ValidationError,
"CheckCash: invalid DeliverMin"
);
});
});

View File

@@ -1,123 +1,127 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyCheckCreate } from './../../src/models/transactions/checkCreate'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyCheckCreate } from "../../src/models/transactions/checkCreate";
/**
* CheckCreate Transaction Verification Testing
* CheckCreate Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('CheckCreate Transaction Verification', function () {
it (`verifies valid CheckCreate`, () => {
const validCheck = {
TransactionType : "CheckCreate",
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax : "100000000",
Expiration : 570113521,
InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag : 1,
Fee : "12"
} as any
assert.doesNotThrow(() => verifyCheckCreate(validCheck))
})
describe("CheckCreate Transaction Verification", function () {
it(`verifies valid CheckCreate`, function () {
const validCheck = {
TransactionType: "CheckCreate",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax: "100000000",
Expiration: 570113521,
InvoiceID:
"6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag: 1,
Fee: "12",
} as any;
assert.doesNotThrow(() => verifyCheckCreate(validCheck));
});
it (`throws w/ invalid Destination`, () => {
const invalidDestination = {
TransactionType : "CheckCreate",
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination : 7896214563214789632154,
SendMax : "100000000",
Expiration : 570113521,
InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag : 1,
Fee : "12"
} as any
it(`throws w/ invalid Destination`, function () {
const invalidDestination = {
TransactionType: "CheckCreate",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination: 7896214563214789632154,
SendMax: "100000000",
Expiration: 570113521,
InvoiceID:
"6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag: 1,
Fee: "12",
} as any;
assert.throws(
() => verifyCheckCreate(invalidDestination),
ValidationError,
"CheckCreate: invalid Destination"
)
})
assert.throws(
() => verifyCheckCreate(invalidDestination),
ValidationError,
"CheckCreate: invalid Destination"
);
});
it (`throws w/ invalid SendMax`, () => {
const invalidSendMax = {
TransactionType : "CheckCreate",
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax : 100000000,
Expiration : 570113521,
InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag : 1,
Fee : "12"
} as any
it(`throws w/ invalid SendMax`, function () {
const invalidSendMax = {
TransactionType: "CheckCreate",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax: 100000000,
Expiration: 570113521,
InvoiceID:
"6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag: 1,
Fee: "12",
} as any;
assert.throws(
() => verifyCheckCreate(invalidSendMax),
ValidationError,
"CheckCreate: invalid SendMax"
)
})
assert.throws(
() => verifyCheckCreate(invalidSendMax),
ValidationError,
"CheckCreate: invalid SendMax"
);
});
it (`throws w/ invalid DestinationTag`, () => {
const invalidDestinationTag = {
TransactionType : "CheckCreate",
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax : "100000000",
Expiration : 570113521,
InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag : "1",
Fee : "12"
} as any
it(`throws w/ invalid DestinationTag`, function () {
const invalidDestinationTag = {
TransactionType: "CheckCreate",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax: "100000000",
Expiration: 570113521,
InvoiceID:
"6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag: "1",
Fee: "12",
} as any;
assert.throws(
() => verifyCheckCreate(invalidDestinationTag),
ValidationError,
"CheckCreate: invalid DestinationTag"
)
})
assert.throws(
() => verifyCheckCreate(invalidDestinationTag),
ValidationError,
"CheckCreate: invalid DestinationTag"
);
});
it (`throws w/ invalid Expiration`, () => {
const invalidExpiration = {
TransactionType : "CheckCreate",
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax : "100000000",
Expiration : "570113521",
InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag : 1,
Fee : "12"
} as any
it(`throws w/ invalid Expiration`, function () {
const invalidExpiration = {
TransactionType: "CheckCreate",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax: "100000000",
Expiration: "570113521",
InvoiceID:
"6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
DestinationTag: 1,
Fee: "12",
} as any;
assert.throws(
() => verifyCheckCreate(invalidExpiration),
ValidationError,
"CheckCreate: invalid Expiration"
)
})
assert.throws(
() => verifyCheckCreate(invalidExpiration),
ValidationError,
"CheckCreate: invalid Expiration"
);
});
it (`throws w/ invalid InvoiceID`, () => {
const invalidInvoiceID = {
TransactionType : "CheckCreate",
Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax : "100000000",
Expiration : 570113521,
InvoiceID : 7896545655285446963258531,
DestinationTag : 1,
Fee : "12"
} as any
it(`throws w/ invalid InvoiceID`, function () {
const invalidInvoiceID = {
TransactionType: "CheckCreate",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
SendMax: "100000000",
Expiration: 570113521,
InvoiceID: 7896545655285446963258531,
DestinationTag: 1,
Fee: "12",
} as any;
assert.throws(
() => verifyCheckCreate(invalidInvoiceID),
ValidationError,
"CheckCreate: invalid InvoiceID"
)
})
})
assert.throws(
() => verifyCheckCreate(invalidInvoiceID),
ValidationError,
"CheckCreate: invalid InvoiceID"
);
});
});

View File

@@ -1,83 +1,85 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyDepositPreauth } from './../../src/models/transactions/depositPreauth'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyDepositPreauth } from "../../src/models/transactions/depositPreauth";
/**
* DepositPreauth Transaction Verification Testing
* DepositPreauth Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('DepositPreauth Transaction Verification', () => {
let depositPreauth
describe("DepositPreauth Transaction Verification", function () {
let depositPreauth;
beforeEach(() => {
depositPreauth = {
TransactionType: 'DepositPreauth',
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
} as any
})
beforeEach(function () {
depositPreauth = {
TransactionType: "DepositPreauth",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
} as any;
});
it ('verifies valid DepositPreauth when only Authorize is provided', () => {
depositPreauth.Authorize = 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW'
assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth))
})
it("verifies valid DepositPreauth when only Authorize is provided", function () {
depositPreauth.Authorize = "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW";
assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth));
});
it ('verifies valid DepositPreauth when only Unauthorize is provided', () => {
depositPreauth.Unauthorize = 'raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n'
assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth))
})
it("verifies valid DepositPreauth when only Unauthorize is provided", function () {
depositPreauth.Unauthorize = "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n";
assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth));
});
it ('throws when both Authorize and Unauthorize are provided', () => {
depositPreauth.Authorize = 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW'
depositPreauth.Unauthorize = 'raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n'
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: can't provide both Authorize and Unauthorize fields"
)
})
it("throws when both Authorize and Unauthorize are provided", function () {
depositPreauth.Authorize = "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW";
depositPreauth.Unauthorize = "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n";
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: can't provide both Authorize and Unauthorize fields"
);
});
it ('throws when neither Authorize nor Unauthorize are provided', () => {
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
'DepositPreauth: must provide either Authorize or Unauthorize field'
)
})
it("throws when neither Authorize nor Unauthorize are provided", function () {
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: must provide either Authorize or Unauthorize field"
);
});
it ('throws when Authorize is not a string', () => {
depositPreauth.Authorize = 1234
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
'DepositPreauth: Authorize must be a string'
)
})
it("throws when Authorize is not a string", function () {
depositPreauth.Authorize = 1234;
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: Authorize must be a string"
);
});
it ('throws when an Account attempts to preauthorize its own address', () => {
depositPreauth.Authorize = depositPreauth.Account
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: Account can't preauthorize its own address"
)
})
it("throws when an Account attempts to preauthorize its own address", function () {
depositPreauth.Authorize = depositPreauth.Account;
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: Account can't preauthorize its own address"
);
});
it ('throws when Unauthorize is not a string', () => {
depositPreauth.Unauthorize = 1234
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
'DepositPreauth: Unauthorize must be a string'
)
})
it("throws when Unauthorize is not a string", function () {
depositPreauth.Unauthorize = 1234;
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: Unauthorize must be a string"
);
});
it ('throws when an Account attempts to unauthorize its own address', () => {
depositPreauth.Unauthorize = depositPreauth.Account
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: Account can't unauthorize its own address"
)
})
})
it("throws when an Account attempts to unauthorize its own address", function () {
depositPreauth.Unauthorize = depositPreauth.Account;
assert.throws(
() => verifyDepositPreauth(depositPreauth),
ValidationError,
"DepositPreauth: Account can't unauthorize its own address"
);
});
});

View File

@@ -1,65 +1,66 @@
import { verifyEscrowCancel } from './../../src/models/transactions/escrowCancel'
import { assert } from 'chai'
import { ValidationError } from '../../src/common/errors'
import { assert } from "chai";
import { ValidationError } from "../../src/common/errors";
import { verifyEscrowCancel } from "../../src/models/transactions/escrowCancel";
/**
* Transaction Verification Testing
* Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('Transaction Verification', function () {
let cancel
describe("Transaction Verification", function () {
let cancel;
beforeEach(() => {
cancel = {
TransactionType: "EscrowCancel",
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
OfferSequence: 7,
}
})
beforeEach(function () {
cancel = {
TransactionType: "EscrowCancel",
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
OfferSequence: 7,
};
});
it (`Valid EscrowCancel`, () => {
assert.doesNotThrow(() => verifyEscrowCancel(cancel))
})
it(`Valid EscrowCancel`, function () {
assert.doesNotThrow(() => verifyEscrowCancel(cancel));
});
it (`Invalid EscrowCancel missing owner`, () => {
delete cancel.Owner
it(`Invalid EscrowCancel missing owner`, function () {
delete cancel.Owner;
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
'EscrowCancel: missing Owner'
)
})
it (`Invalid EscrowCancel missing offerSequence`, () => {
delete cancel.OfferSequence
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
"EscrowCancel: missing Owner"
);
});
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
'EscrowCancel: missing OfferSequence'
)
})
it(`Invalid EscrowCancel missing offerSequence`, function () {
delete cancel.OfferSequence;
it (`Invalid OfferSequence`, () => {
cancel.Owner = 10
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
"EscrowCancel: missing OfferSequence"
);
});
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
'EscrowCancel: Owner must be a string'
)
})
it(`Invalid OfferSequence`, function () {
cancel.Owner = 10;
it (`Invalid owner`, () => {
cancel.OfferSequence = "10"
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
"EscrowCancel: Owner must be a string"
);
});
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
'EscrowCancel: OfferSequence must be a number'
)
})
})
it(`Invalid owner`, function () {
cancel.OfferSequence = "10";
assert.throws(
() => verifyEscrowCancel(cancel),
ValidationError,
"EscrowCancel: OfferSequence must be a number"
);
});
});

View File

@@ -1,132 +1,135 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyEscrowCreate } from './../../src/models/transactions/escrowCreate'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyEscrowCreate } from "../../src/models/transactions/escrowCreate";
/**
* EscrowCreate Transaction Verification Testing
* EscrowCreate Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('EscrowCreate Transaction Verification', function () {
let escrow
describe("EscrowCreate Transaction Verification", function () {
let escrow;
beforeEach(() => {
escrow = {
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
TransactionType: "EscrowCreate",
Amount: "10000",
Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
CancelAfter: 533257958,
FinishAfter: 533171558,
Condition: "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
DestinationTag: 23480,
SourceTag: 11747
}
})
it (`verifies valid EscrowCreate`, () => {
assert.doesNotThrow(() => verifyEscrowCreate(escrow))
})
beforeEach(function () {
escrow = {
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
TransactionType: "EscrowCreate",
Amount: "10000",
Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
CancelAfter: 533257958,
FinishAfter: 533171558,
Condition:
"A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
DestinationTag: 23480,
SourceTag: 11747,
};
});
it (`Missing amount`, () => {
delete escrow.Amount
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: missing field Amount"
)
})
it(`verifies valid EscrowCreate`, function () {
assert.doesNotThrow(() => verifyEscrowCreate(escrow));
});
it (`Missing destination`, () => {
delete escrow.Destination
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: missing field Destination"
)
})
it(`Missing amount`, function () {
delete escrow.Amount;
it (`throws w/ invalid Destination`, () => {
escrow.Destination = 10
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: missing field Amount"
);
});
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Destination must be a string"
)
})
it(`Missing destination`, function () {
delete escrow.Destination;
it (`throws w/ invalid Amount`, () => {
escrow.Amount = 1000
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: missing field Destination"
);
});
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Amount must be a string"
)
})
it(`throws w/ invalid Destination`, function () {
escrow.Destination = 10;
it (`invalid CancelAfter`, () => {
escrow.CancelAfter = "100"
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: CancelAfter must be a number"
)
})
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Destination must be a string"
);
});
it (`invalid FinishAfter`, () => {
escrow.FinishAfter = "1000"
it(`throws w/ invalid Amount`, function () {
escrow.Amount = 1000;
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: FinishAfter must be a number"
)
})
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Amount must be a string"
);
});
it (`invalid Condition`, () => {
escrow.Condition = 0x141243
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Condition must be a string"
)
})
it(`invalid CancelAfter`, function () {
escrow.CancelAfter = "100";
it (`invalid DestinationTag`, () => {
escrow.DestinationTag = "100"
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: DestinationTag must be a number"
)
})
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: CancelAfter must be a number"
);
});
it (`Missing both CancelAfter and FinishAfter`, () => {
delete escrow.CancelAfter
delete escrow.FinishAfter
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Either CancelAfter or FinishAfter must be specified"
)
})
it(`invalid FinishAfter`, function () {
escrow.FinishAfter = "1000";
it (`Missing both Condition and FinishAfter`, () => {
delete escrow.Condition
delete escrow.FinishAfter
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Either Condition or FinishAfter must be specified"
)
})
})
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: FinishAfter must be a number"
);
});
it(`invalid Condition`, function () {
escrow.Condition = 0x141243;
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Condition must be a string"
);
});
it(`invalid DestinationTag`, function () {
escrow.DestinationTag = "100";
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: DestinationTag must be a number"
);
});
it(`Missing both CancelAfter and FinishAfter`, function () {
delete escrow.CancelAfter;
delete escrow.FinishAfter;
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Either CancelAfter or FinishAfter must be specified"
);
});
it(`Missing both Condition and FinishAfter`, function () {
delete escrow.Condition;
delete escrow.FinishAfter;
assert.throws(
() => verifyEscrowCreate(escrow),
ValidationError,
"EscrowCreate: Either Condition or FinishAfter must be specified"
);
});
});

View File

@@ -1,75 +1,76 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyEscrowFinish } from './../../src/models/transactions/escrowFinish'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyEscrowFinish } from "../../src/models/transactions/escrowFinish";
/**
* EscrowFinish Transaction Verification Testing
* EscrowFinish Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('EscrowFinish Transaction Verification', function () {
let escrow
describe("EscrowFinish Transaction Verification", function () {
let escrow;
beforeEach(() => {
escrow = {
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
TransactionType: "EscrowFinish",
Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
OfferSequence: 7,
Condition: "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
Fulfillment: "A0028000"
}
})
it (`verifies valid EscrowFinish`, () => {
assert.doesNotThrow(() => verifyEscrowFinish(escrow))
})
beforeEach(function () {
escrow = {
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
TransactionType: "EscrowFinish",
Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
OfferSequence: 7,
Condition:
"A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100",
Fulfillment: "A0028000",
};
});
it(`verifies valid EscrowFinish`, function () {
assert.doesNotThrow(() => verifyEscrowFinish(escrow));
});
it (`verifies valid EscrowFinish w/o optional`, () => {
delete escrow.Condition
delete escrow.Fulfillment
assert.doesNotThrow(() => verifyEscrowFinish(escrow))
})
it(`verifies valid EscrowFinish w/o optional`, function () {
delete escrow.Condition;
delete escrow.Fulfillment;
assert.doesNotThrow(() => verifyEscrowFinish(escrow));
});
it (`throws w/ invalid Owner`, () => {
escrow.Owner = 0x15415253
it(`throws w/ invalid Owner`, function () {
escrow.Owner = 0x15415253;
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: Owner must be a string"
)
})
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: Owner must be a string"
);
});
it (`throws w/ invalid OfferSequence`, () => {
escrow.OfferSequence = "10"
it(`throws w/ invalid OfferSequence`, function () {
escrow.OfferSequence = "10";
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: OfferSequence must be a number"
)
})
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: OfferSequence must be a number"
);
});
it (`throws w/ invalid Condition`, () => {
escrow.Condition = 10
it(`throws w/ invalid Condition`, function () {
escrow.Condition = 10;
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: Condition must be a string"
)
})
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: Condition must be a string"
);
});
it (`throws w/ invalid Fulfillment`, () => {
escrow.Fulfillment = 0x142341
it(`throws w/ invalid Fulfillment`, function () {
escrow.Fulfillment = 0x142341;
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: Fulfillment must be a string"
)
})
})
assert.throws(
() => verifyEscrowFinish(escrow),
ValidationError,
"EscrowFinish: Fulfillment must be a string"
);
});
});

View File

@@ -1,53 +1,57 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyOfferCancel } from './../../src/models/transactions/offerCancel'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyOfferCancel } from "../../src/models/transactions/offerCancel";
/**
* OfferCancel Transaction Verification Testing
* OfferCancel Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('OfferCancel Transaction Verification', function () {
let offer
beforeEach(() => {
offer = {
Account: "rnKiczmiQkZFiDES8THYyLA2pQohC5C6EF",
Fee: "10",
LastLedgerSequence: 65477334,
OfferSequence: 60797528,
Sequence: 60797535,
SigningPubKey: "0361BFD43D1EEA54B77CC152887312949EBF052997FBFFCDAF6F2653164B55B21...",
TransactionType: "OfferCancel",
TxnSignature: "30450221008C43BDCFC68B4793857CA47DF454C07E5B45D3F80E8E6785CAB9292...",
date: "2021-08-06T21:04:11Z"
} as any
})
describe("OfferCancel Transaction Verification", function () {
let offer;
it (`verifies valid OfferCancel`, () => {
assert.doesNotThrow(() => verifyOfferCancel(offer))
})
beforeEach(function () {
offer = {
Account: "rnKiczmiQkZFiDES8THYyLA2pQohC5C6EF",
Fee: "10",
LastLedgerSequence: 65477334,
OfferSequence: 60797528,
Sequence: 60797535,
SigningPubKey:
"0361BFD43D1EEA54B77CC152887312949EBF052997FBFFCDAF6F2653164B55B21...",
TransactionType: "OfferCancel",
TxnSignature:
"30450221008C43BDCFC68B4793857CA47DF454C07E5B45D3F80E8E6785CAB9292...",
date: "2021-08-06T21:04:11Z",
} as any;
});
it (`verifies valid OfferCancel with flags`, () => {
offer.Flags = 2147483648
assert.doesNotThrow(() => verifyOfferCancel(offer))
})
it(`verifies valid OfferCancel`, function () {
assert.doesNotThrow(() => verifyOfferCancel(offer));
});
it (`throws w/ OfferSequence must be a number`, () => {
offer.OfferSequence = '99'
assert.throws(
() => verifyOfferCancel(offer),
ValidationError,
"OfferCancel: OfferSequence must be a number"
)
})
it(`verifies valid OfferCancel with flags`, function () {
offer.Flags = 2147483648;
assert.doesNotThrow(() => verifyOfferCancel(offer));
});
it (`throws w/ missing OfferSequence`, () => {
delete offer.OfferSequence
assert.throws(
() => verifyOfferCancel(offer),
ValidationError,
"OfferCancel: missing field OfferSequence"
)
})
})
it(`throws w/ OfferSequence must be a number`, function () {
offer.OfferSequence = "99";
assert.throws(
() => verifyOfferCancel(offer),
ValidationError,
"OfferCancel: OfferSequence must be a number"
);
});
it(`throws w/ missing OfferSequence`, function () {
delete offer.OfferSequence;
assert.throws(
() => verifyOfferCancel(offer),
ValidationError,
"OfferCancel: missing field OfferSequence"
);
});
});

View File

@@ -1,177 +1,191 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyOfferCreate } from './../../src/models/transactions/offerCreate'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyOfferCreate } from "../../src/models/transactions/offerCreate";
/**
* OfferCreate Transaction Verification Testing
* OfferCreate Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('OfferCreate Transaction Verification', function () {
it (`verifies valid OfferCreate`, () => {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
Expiration: 10,
OfferSequence: 12,
TakerGets: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009"
},
TakerPays: "12928290425",
TransactionType: "OfferCreate",
TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any
assert.doesNotThrow(() => verifyOfferCreate(offer))
describe("OfferCreate Transaction Verification", function () {
it(`verifies valid OfferCreate`, function () {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey:
"03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
Expiration: 10,
OfferSequence: 12,
TakerGets: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009",
},
TakerPays: "12928290425",
TransactionType: "OfferCreate",
TxnSignature:
"3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any;
const offer2 = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
TakerGets: "12928290425",
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009"
},
TransactionType: "OfferCreate",
TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any
assert.doesNotThrow(() => verifyOfferCreate(offer));
assert.doesNotThrow(() => verifyOfferCreate(offer2))
const offer2 = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey:
"03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
TakerGets: "12928290425",
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009",
},
TransactionType: "OfferCreate",
TxnSignature:
"3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any;
assert.doesNotThrow(() => verifyOfferCreate(offer2));
const offer3 = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
TakerGets: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009"
},
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009"
},
TransactionType: "OfferCreate",
TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any
const offer3 = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey:
"03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
TakerGets: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009",
},
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009",
},
TransactionType: "OfferCreate",
TxnSignature:
"3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any;
assert.doesNotThrow(() => verifyOfferCreate(offer3))
})
assert.doesNotThrow(() => verifyOfferCreate(offer3));
});
it (`throws w/ invalid Expiration`, () => {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
Expiration: "11",
TakerGets: "12928290425",
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009"
},
TransactionType: "OfferCreate",
TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any
it(`throws w/ invalid Expiration`, function () {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey:
"03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
Expiration: "11",
TakerGets: "12928290425",
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009",
},
TransactionType: "OfferCreate",
TxnSignature:
"3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any;
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid Expiration"
)
})
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid Expiration"
);
});
it (`throws w/ invalid OfferSequence`, () => {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
OfferSequence: "11",
TakerGets: "12928290425",
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009"
},
TransactionType: "OfferCreate",
TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any
it(`throws w/ invalid OfferSequence`, function () {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey:
"03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
OfferSequence: "11",
TakerGets: "12928290425",
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009",
},
TransactionType: "OfferCreate",
TxnSignature:
"3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any;
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid OfferSequence"
)
})
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid OfferSequence"
);
});
it (`throws w/ invalid TakerPays`, () => {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
OfferSequence: "11",
TakerGets: "12928290425",
TakerPays: 10,
TransactionType: "OfferCreate",
TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any
it(`throws w/ invalid TakerPays`, function () {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey:
"03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
OfferSequence: "11",
TakerGets: "12928290425",
TakerPays: 10,
TransactionType: "OfferCreate",
TxnSignature:
"3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any;
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid TakerPays"
)
})
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid TakerPays"
);
});
it (`throws w/ invalid TakerGets`, () => {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
OfferSequence: "11",
TakerGets: 11,
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009"
},
TransactionType: "OfferCreate",
TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any
it(`throws w/ invalid TakerGets`, function () {
const offer = {
Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W",
Fee: "10",
Flags: 0,
LastLedgerSequence: 65453019,
Sequence: 40949322,
SigningPubKey:
"03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22",
OfferSequence: "11",
TakerGets: 11,
TakerPays: {
currency: "DSH",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "43.11584856965009",
},
TransactionType: "OfferCreate",
TxnSignature:
"3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91",
} as any;
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid TakerGets"
)
})
})
assert.throws(
() => verifyOfferCreate(offer),
ValidationError,
"OfferCreate: invalid TakerGets"
);
});
});

View File

@@ -1,98 +1,102 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyPaymentChannelClaim } from './../../src/models/transactions/paymentChannelClaim'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyPaymentChannelClaim } from "../../src/models/transactions/paymentChannelClaim";
/**
* PaymentChannelClaim Transaction Verification Testing
* PaymentChannelClaim Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('PaymentChannelClaim Transaction Verification', function () {
let channel
describe("PaymentChannelClaim Transaction Verification", function () {
let channel;
beforeEach(() => {
channel = {
"Account": "r...",
"TransactionType": "PaymentChannelClaim",
"Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198",
"Balance": "1000000",
"Amount": "1000000",
"Signature": "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B",
"PublicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A"
}
})
beforeEach(function () {
channel = {
Account: "r...",
TransactionType: "PaymentChannelClaim",
Channel:
"C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198",
Balance: "1000000",
Amount: "1000000",
Signature:
"30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B",
PublicKey:
"32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A",
};
});
it (`verifies valid PaymentChannelClaim`, () => {
assert.doesNotThrow(() => verifyPaymentChannelClaim(channel))
})
it(`verifies valid PaymentChannelClaim`, function () {
assert.doesNotThrow(() => verifyPaymentChannelClaim(channel));
});
it (`verifies valid PaymentChannelClaim w/o optional`, () => {
delete channel.Balance
delete channel.Amount
delete channel.Signature
delete channel.PublicKey
assert.doesNotThrow(() => verifyPaymentChannelClaim(channel))
})
it(`verifies valid PaymentChannelClaim w/o optional`, function () {
delete channel.Balance;
delete channel.Amount;
delete channel.Signature;
delete channel.PublicKey;
it (`throws w/ missing Channel`, () => {
delete channel.Channel
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: missing Channel"
)
})
assert.doesNotThrow(() => verifyPaymentChannelClaim(channel));
});
it (`throws w/ invalid Channel`, () => {
channel.Channel = 100
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Channel must be a string"
)
})
it(`throws w/ missing Channel`, function () {
delete channel.Channel;
it (`throws w/ invalid Balance`, () => {
channel.Balance = 100
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Balance must be a string"
)
})
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: missing Channel"
);
});
it (`throws w/ invalid Amount`, () => {
channel.Amount = 1000
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Amount must be a string"
)
})
it(`throws w/ invalid Channel`, function () {
channel.Channel = 100;
it (`throws w/ invalid Signature`, () => {
channel.Signature = 1000
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Signature must be a string"
)
})
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Channel must be a string"
);
});
it (`throws w/ invalid PublicKey`, () => {
channel.PublicKey = ["100000"]
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: PublicKey must be a string"
)
})
})
it(`throws w/ invalid Balance`, function () {
channel.Balance = 100;
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Balance must be a string"
);
});
it(`throws w/ invalid Amount`, function () {
channel.Amount = 1000;
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Amount must be a string"
);
});
it(`throws w/ invalid Signature`, function () {
channel.Signature = 1000;
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: Signature must be a string"
);
});
it(`throws w/ invalid PublicKey`, function () {
channel.PublicKey = ["100000"];
assert.throws(
() => verifyPaymentChannelClaim(channel),
ValidationError,
"PaymentChannelClaim: PublicKey must be a string"
);
});
});

View File

@@ -1,140 +1,141 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyPaymentChannelCreate } from './../../src/models/transactions/paymentChannelCreate'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyPaymentChannelCreate } from "../../src/models/transactions/paymentChannelCreate";
/**
* PaymentChannelCreate Transaction Verification Testing
* PaymentChannelCreate Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('PaymentChannelCreate Transaction Verification', function () {
let channel
describe("PaymentChannelCreate Transaction Verification", function () {
let channel;
beforeEach(() => {
channel = {
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
"TransactionType": "PaymentChannelCreate",
"Amount": "10000",
"Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
"SettleDelay": 86400,
"PublicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A",
"CancelAfter": 533171558,
"DestinationTag": 23480,
"SourceTag": 11747
}
})
it (`verifies valid PaymentChannelCreate`, () => {
assert.doesNotThrow(() => verifyPaymentChannelCreate(channel))
})
beforeEach(function () {
channel = {
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
TransactionType: "PaymentChannelCreate",
Amount: "10000",
Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
SettleDelay: 86400,
PublicKey:
"32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A",
CancelAfter: 533171558,
DestinationTag: 23480,
SourceTag: 11747,
};
});
it (`verifies valid PaymentChannelCreate w/o optional`, () => {
delete channel.CancelAfter
delete channel.DestinationTag
delete channel.SourceTag
it(`verifies valid PaymentChannelCreate`, function () {
assert.doesNotThrow(() => verifyPaymentChannelCreate(channel));
});
assert.doesNotThrow(() => verifyPaymentChannelCreate(channel))
})
it(`verifies valid PaymentChannelCreate w/o optional`, function () {
delete channel.CancelAfter;
delete channel.DestinationTag;
delete channel.SourceTag;
it (`missing Amount`, () => {
delete channel.Amount
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing Amount"
)
})
assert.doesNotThrow(() => verifyPaymentChannelCreate(channel));
});
it(`missing Amount`, function () {
delete channel.Amount;
it (`missing Destination`, () => {
delete channel.Destination
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing Destination"
)
})
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing Amount"
);
});
it (`missing SettleDelay`, () => {
delete channel.SettleDelay
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing SettleDelay"
)
})
it(`missing Destination`, function () {
delete channel.Destination;
it (`missing PublicKey`, () => {
delete channel.PublicKey
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing PublicKey"
)
})
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing Destination"
);
});
it (`invalid Amount`, () => {
channel.Amount = 1000
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: Amount must be a string"
)
})
it(`missing SettleDelay`, function () {
delete channel.SettleDelay;
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing SettleDelay"
);
});
it (`invalid Destination`, () => {
channel.Destination = 10;
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: Destination must be a string"
)
})
it(`missing PublicKey`, function () {
delete channel.PublicKey;
it (`invalid SettleDelay`, () => {
channel.SettleDelay = "10"
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: SettleDelay must be a number"
)
})
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: missing PublicKey"
);
});
it (`invalid PublicKey`, () => {
channel.PublicKey = 10
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: PublicKey must be a string"
)
})
it(`invalid Amount`, function () {
channel.Amount = 1000;
it (`invalid DestinationTag`, () => {
channel.DestinationTag = "10"
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: Amount must be a string"
);
});
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: DestinationTag must be a number"
)
})
it(`invalid Destination`, function () {
channel.Destination = 10;
it (`invalid CancelAfter`, () => {
channel.CancelAfter = "100"
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: CancelAfter must be a number"
)
})
})
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: Destination must be a string"
);
});
it(`invalid SettleDelay`, function () {
channel.SettleDelay = "10";
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: SettleDelay must be a number"
);
});
it(`invalid PublicKey`, function () {
channel.PublicKey = 10;
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: PublicKey must be a string"
);
});
it(`invalid DestinationTag`, function () {
channel.DestinationTag = "10";
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: DestinationTag must be a number"
);
});
it(`invalid CancelAfter`, function () {
channel.CancelAfter = "100";
assert.throws(
() => verifyPaymentChannelCreate(channel),
ValidationError,
"PaymentChannelCreate: CancelAfter must be a number"
);
});
});

View File

@@ -1,83 +1,85 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyPaymentChannelFund } from './../../src/models/transactions/paymentChannelFund'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyPaymentChannelFund } from "../../src/models/transactions/paymentChannelFund";
/**
* PaymentChannelFund Transaction Verification Testing
* PaymentChannelFund Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('PaymentChannelFund Transaction Verification', function () {
let channel
describe("PaymentChannelFund Transaction Verification", function () {
let channel;
beforeEach(() => {
channel = {
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
"TransactionType": "PaymentChannelFund",
"Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198",
"Amount": "200000",
"Expiration": 543171558
}
})
it (`verifies valid PaymentChannelFund`, () => {
assert.doesNotThrow(() => verifyPaymentChannelFund(channel))
})
beforeEach(function () {
channel = {
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
TransactionType: "PaymentChannelFund",
Channel:
"C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198",
Amount: "200000",
Expiration: 543171558,
};
});
it (`verifies valid PaymentChannelFund w/o optional`, () => {
delete channel.Expiration
assert.doesNotThrow(() => verifyPaymentChannelFund(channel))
})
it(`verifies valid PaymentChannelFund`, function () {
assert.doesNotThrow(() => verifyPaymentChannelFund(channel));
});
it (`throws w/ missing Amount`, () => {
delete channel.Amount
it(`verifies valid PaymentChannelFund w/o optional`, function () {
delete channel.Expiration;
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: missing Amount"
)
})
assert.doesNotThrow(() => verifyPaymentChannelFund(channel));
});
it (`throws w/ missing Channel`, () => {
delete channel.Channel
it(`throws w/ missing Amount`, function () {
delete channel.Amount;
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: missing Channel"
)
})
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: missing Amount"
);
});
it (`throws w/ invalid Amount`, () => {
channel.Amount = 100
it(`throws w/ missing Channel`, function () {
delete channel.Channel;
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: Amount must be a string"
)
})
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: missing Channel"
);
});
it (`throws w/ invalid Channel`, () => {
channel.Channel = 1000
it(`throws w/ invalid Amount`, function () {
channel.Amount = 100;
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: Channel must be a string"
)
})
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: Amount must be a string"
);
});
it (`throws w/ invalid Expiration`, () => {
channel.Expiration = "1000"
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: Expiration must be a number"
)
})
it(`throws w/ invalid Channel`, function () {
channel.Channel = 1000;
})
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: Channel must be a string"
);
});
it(`throws w/ invalid Expiration`, function () {
channel.Expiration = "1000";
assert.throws(
() => verifyPaymentChannelFund(channel),
ValidationError,
"PaymentChannelFund: Expiration must be a number"
);
});
});

View File

@@ -1,132 +1,140 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { PaymentTransactionFlagsEnum, verifyPaymentTransaction } from './../../src/models/transactions/paymentTransaction'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import {
PaymentTransactionFlagsEnum,
verifyPaymentTransaction,
} from "../../src/models/transactions/paymentTransaction";
/**
* PaymentTransaction Verification Testing
* PaymentTransaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('Payment Transaction Verification', () => {
let paymentTransaction
describe("Payment Transaction Verification", function () {
let paymentTransaction;
beforeEach(() => {
paymentTransaction = {
TransactionType: 'Payment',
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
Amount: '1234',
Destination: 'rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy',
DestinationTag: 1,
InvoiceID: '6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B',
Paths: [[{ account: 'aw0efji', currency: 'XRP', issuer: 'apsoeijf90wp34fh'}]],
SendMax: '100000000',
} as any
})
beforeEach(function () {
paymentTransaction = {
TransactionType: "Payment",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
Amount: "1234",
Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
DestinationTag: 1,
InvoiceID:
"6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
Paths: [
[{ account: "aw0efji", currency: "XRP", issuer: "apsoeijf90wp34fh" }],
],
SendMax: "100000000",
} as any;
});
it (`verifies valid PaymentTransaction`, () => {
assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction))
})
it(`verifies valid PaymentTransaction`, function () {
assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction));
});
it (`throws when Amount is missing`, () => {
delete paymentTransaction.Amount
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: missing field Amount'
)
})
it(`throws when Amount is missing`, function () {
delete paymentTransaction.Amount;
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: missing field Amount"
);
});
it (`throws when Amount is invalid`, () => {
paymentTransaction.Amount = 1234
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: invalid Amount'
)
})
it(`throws when Amount is invalid`, function () {
paymentTransaction.Amount = 1234;
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: invalid Amount"
);
});
it (`throws when Destination is missing`, () => {
delete paymentTransaction.Destination
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: missing field Destination'
)
})
it(`throws when Destination is missing`, function () {
delete paymentTransaction.Destination;
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: missing field Destination"
);
});
it (`throws when Destination is invalid`, () => {
paymentTransaction.Destination = 7896214
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: invalid Destination'
)
})
it(`throws when Destination is invalid`, function () {
paymentTransaction.Destination = 7896214;
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: invalid Destination"
);
});
it (`throws when DestinationTag is not a number`, () => {
paymentTransaction.DestinationTag = '1'
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: DestinationTag must be a number'
)
})
it(`throws when DestinationTag is not a number`, function () {
paymentTransaction.DestinationTag = "1";
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: DestinationTag must be a number"
);
});
it (`throws when InvoiceID is not a string`, () => {
paymentTransaction.InvoiceID = 19832
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: InvoiceID must be a string'
)
})
it(`throws when InvoiceID is not a string`, function () {
paymentTransaction.InvoiceID = 19832;
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: InvoiceID must be a string"
);
});
it (`throws when Paths is invalid`, () => {
paymentTransaction.Paths = [[{ account: 123 }]]
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: invalid Paths'
)
})
it(`throws when Paths is invalid`, function () {
paymentTransaction.Paths = [[{ account: 123 }]];
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: invalid Paths"
);
});
it (`throws when SendMax is invalid`, () => {
paymentTransaction.SendMax = 100000000
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: invalid SendMax'
)
})
it(`throws when SendMax is invalid`, function () {
paymentTransaction.SendMax = 100000000;
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: invalid SendMax"
);
});
it (`verifies valid DeliverMin with tfPartialPayment flag set as a number`, () => {
paymentTransaction.DeliverMin = '10000'
paymentTransaction.Flags = PaymentTransactionFlagsEnum.tfPartialPayment,
assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction))
})
it(`verifies valid DeliverMin with tfPartialPayment flag set as a number`, function () {
paymentTransaction.DeliverMin = "10000";
(paymentTransaction.Flags = PaymentTransactionFlagsEnum.tfPartialPayment),
assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction));
});
it (`verifies valid DeliverMin with tfPartialPayment flag set as a boolean`, () => {
paymentTransaction.DeliverMin = '10000'
paymentTransaction.Flags = { tfPartialPayment: true }
assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction))
})
it(`verifies valid DeliverMin with tfPartialPayment flag set as a boolean`, function () {
paymentTransaction.DeliverMin = "10000";
paymentTransaction.Flags = { tfPartialPayment: true };
assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction));
});
it (`throws when DeliverMin is invalid`, () => {
paymentTransaction.DeliverMin = 10000
paymentTransaction.Flags = { tfPartialPayment: true }
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: invalid DeliverMin'
)
})
it(`throws when DeliverMin is invalid`, function () {
paymentTransaction.DeliverMin = 10000;
paymentTransaction.Flags = { tfPartialPayment: true };
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: invalid DeliverMin"
);
});
it (`throws when tfPartialPayment flag is missing with valid DeliverMin`, () => {
paymentTransaction.DeliverMin = '10000'
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
'PaymentTransaction: tfPartialPayment flag required with DeliverMin'
)
})
})
it(`throws when tfPartialPayment flag is missing with valid DeliverMin`, function () {
paymentTransaction.DeliverMin = "10000";
assert.throws(
() => verifyPaymentTransaction(paymentTransaction),
ValidationError,
"PaymentTransaction: tfPartialPayment flag required with DeliverMin"
);
});
});

View File

@@ -1,42 +1,43 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifySetRegularKey } from './../../src/models/transactions/setRegularKey'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifySetRegularKey } from "../../src/models/transactions/setRegularKey";
/**
* SetRegularKey Transaction Verification Testing
* SetRegularKey Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('SetRegularKey Transaction Verification', function () {
let account
describe("SetRegularKey Transaction Verification", function () {
let account;
beforeEach(() => {
account = {
TransactionType : "SetRegularKey",
Account : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Fee : "12",
Flags : 0,
RegularKey : "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD"
} as any
})
beforeEach(function () {
account = {
TransactionType: "SetRegularKey",
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Fee: "12",
Flags: 0,
RegularKey: "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD",
} as any;
});
it (`verifies valid SetRegularKey`, () => {
assert.doesNotThrow(() => verifySetRegularKey(account))
})
it(`verifies valid SetRegularKey`, function () {
assert.doesNotThrow(() => verifySetRegularKey(account));
});
it (`verifies w/o SetRegularKey`, () => {
account.RegularKey = undefined
assert.doesNotThrow(() => verifySetRegularKey(account))
})
it(`verifies w/o SetRegularKey`, function () {
account.RegularKey = undefined;
assert.doesNotThrow(() => verifySetRegularKey(account));
});
it (`throws w/ invalid RegularKey`, () => {
account.RegularKey = 12369846963
it(`throws w/ invalid RegularKey`, function () {
account.RegularKey = 12369846963;
assert.throws(
() => verifySetRegularKey(account),
ValidationError,
"SetRegularKey: RegularKey must be a string"
)
})
})
assert.throws(
() => verifySetRegularKey(account),
ValidationError,
"SetRegularKey: RegularKey must be a string"
);
});
});

View File

@@ -1,77 +1,78 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifySignerListSet } from './../../src/models/transactions/signerListSet'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifySignerListSet } from "../../src/models/transactions/signerListSet";
/**
* SignerListSet Transaction Verification Testing
* SignerListSet Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('SignerListSet Transaction Verification', function () {
let SignerListSetTx
describe("SignerListSet Transaction Verification", function () {
let SignerListSetTx;
beforeEach(() => {
SignerListSetTx = {
Flags: 0,
TransactionType: "SignerListSet",
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Fee: "12",
SignerQuorum: 3,
SignerEntries: [
{
SignerEntry: {
Account: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
SignerWeight: 2
}
},
{
SignerEntry: {
Account: "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
SignerWeight: 1
}
},
{
SignerEntry: {
Account: "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
SignerWeight: 1
}
}
]
} as any
})
it (`verifies valid SignerListSet`, () => {
assert.doesNotThrow(() => verifySignerListSet(SignerListSetTx))
})
beforeEach(function () {
SignerListSetTx = {
Flags: 0,
TransactionType: "SignerListSet",
Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
Fee: "12",
SignerQuorum: 3,
SignerEntries: [
{
SignerEntry: {
Account: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
SignerWeight: 2,
},
},
{
SignerEntry: {
Account: "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
SignerWeight: 1,
},
},
{
SignerEntry: {
Account: "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
SignerWeight: 1,
},
},
],
} as any;
});
it(`verifies valid SignerListSet`, function () {
assert.doesNotThrow(() => verifySignerListSet(SignerListSetTx));
});
it (`throws w/ missing SignerQuorum`, () => {
SignerListSetTx.SignerQuorum = undefined
it(`throws w/ missing SignerQuorum`, function () {
SignerListSetTx.SignerQuorum = undefined;
assert.throws(
() => verifySignerListSet(SignerListSetTx),
ValidationError,
"SignerListSet: missing field SignerQuorum"
)
})
assert.throws(
() => verifySignerListSet(SignerListSetTx),
ValidationError,
"SignerListSet: missing field SignerQuorum"
);
});
it (`throws w/ empty SignerEntries`, () => {
SignerListSetTx.SignerEntries = []
it(`throws w/ empty SignerEntries`, function () {
SignerListSetTx.SignerEntries = [];
assert.throws(
() => verifySignerListSet(SignerListSetTx),
ValidationError,
"SignerListSet: need atleast 1 member in SignerEntries"
)
})
assert.throws(
() => verifySignerListSet(SignerListSetTx),
ValidationError,
"SignerListSet: need atleast 1 member in SignerEntries"
);
});
it (`throws w/ invalid SignerEntries`, () => {
SignerListSetTx.SignerEntries = "khgfgyhujk"
assert.throws(
() => verifySignerListSet(SignerListSetTx),
ValidationError,
"SignerListSet: invalid SignerEntries"
)
})
})
it(`throws w/ invalid SignerEntries`, function () {
SignerListSetTx.SignerEntries = "khgfgyhujk";
assert.throws(
() => verifySignerListSet(SignerListSetTx),
ValidationError,
"SignerListSet: invalid SignerEntries"
);
});
});

View File

@@ -1,69 +1,71 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyTicketCreate } from './../../src/models/transactions/ticketCreate'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyTicketCreate } from "../../src/models/transactions/ticketCreate";
/**
* TicketCreate Transaction Verification Testing
* TicketCreate Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('TicketCreate Transaction Verification', () => {
let ticketCreate
describe("TicketCreate Transaction Verification", function () {
let ticketCreate;
beforeEach(() => {
ticketCreate = {
TransactionType: 'TicketCreate',
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
TicketCount: 150,
} as any
})
beforeEach(function () {
ticketCreate = {
TransactionType: "TicketCreate",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
TicketCount: 150,
} as any;
});
it ('verifies valid TicketCreate', () => {
assert.doesNotThrow(() => verifyTicketCreate(ticketCreate))
})
it("verifies valid TicketCreate", function () {
assert.doesNotThrow(() => verifyTicketCreate(ticketCreate));
});
it ('throws when TicketCount is missing', () => {
delete ticketCreate.TicketCount
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
'TicketCreate: missing field TicketCount'
)
})
it("throws when TicketCount is missing", function () {
delete ticketCreate.TicketCount;
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
"TicketCreate: missing field TicketCount"
);
});
it ('throws when TicketCount is not a number', () => {
ticketCreate.TicketCount = '150'
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
'TicketCreate: TicketCount must be a number'
)
})
it("throws when TicketCount is not a number", function () {
ticketCreate.TicketCount = "150";
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
"TicketCreate: TicketCount must be a number"
);
});
it ('throws when TicketCount is not an integer', () => {
ticketCreate.TicketCount = 12.5
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
'TicketCreate: TicketCount must be an integer from 1 to 250'
)
})
it("throws when TicketCount is not an integer", function () {
ticketCreate.TicketCount = 12.5;
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
"TicketCreate: TicketCount must be an integer from 1 to 250"
);
});
it ('throws when TicketCount is < 1', () => {
ticketCreate.TicketCount = 0
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
'TicketCreate: TicketCount must be an integer from 1 to 250'
)
})
it("throws when TicketCount is < 1", function () {
ticketCreate.TicketCount = 0;
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
"TicketCreate: TicketCount must be an integer from 1 to 250"
);
});
it ('throws when TicketCount is > 250', () => {
ticketCreate.TicketCount = 251
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
'TicketCreate: TicketCount must be an integer from 1 to 250'
)
})
})
it("throws when TicketCount is > 250", function () {
ticketCreate.TicketCount = 251;
assert.throws(
() => verifyTicketCreate(ticketCreate),
ValidationError,
"TicketCreate: TicketCount must be an integer from 1 to 250"
);
});
});

View File

@@ -1,66 +1,68 @@
import { ValidationError } from 'xrpl-local/common/errors'
import { verifyTrustSet } from './../../src/models/transactions/trustSet'
import { assert } from 'chai'
import { assert } from "chai";
import { ValidationError } from "xrpl-local/common/errors";
import { verifyTrustSet } from "../../src/models/transactions/trustSet";
/**
* TrustSet Transaction Verification Testing
* TrustSet Transaction Verification Testing.
*
* Providing runtime verification testing for each specific transaction type
* Providing runtime verification testing for each specific transaction type.
*/
describe('TrustSet Transaction Verification', () => {
let trustSet
describe("TrustSet Transaction Verification", function () {
let trustSet;
beforeEach(() => {
trustSet = {
TransactionType: 'TrustSet',
Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo',
LimitAmount: {
currency: 'XRP',
issuer: 'rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX',
value: '4329.23'
},
QualityIn: 1234,
QualityOut: 4321,
} as any
})
beforeEach(function () {
trustSet = {
TransactionType: "TrustSet",
Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
LimitAmount: {
currency: "XRP",
issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX",
value: "4329.23",
},
QualityIn: 1234,
QualityOut: 4321,
} as any;
});
it ('verifies valid TrustSet', () => {
assert.doesNotThrow(() => verifyTrustSet(trustSet))
})
it("verifies valid TrustSet", function () {
assert.doesNotThrow(() => verifyTrustSet(trustSet));
});
it ('throws when LimitAmount is missing', () => {
delete trustSet.LimitAmount
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
'TrustSet: missing field LimitAmount'
)
})
it("throws when LimitAmount is missing", function () {
delete trustSet.LimitAmount;
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
"TrustSet: missing field LimitAmount"
);
});
it ('throws when LimitAmount is invalid', () => {
trustSet.LimitAmount = 1234
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
'TrustSet: invalid LimitAmount'
)
})
it("throws when LimitAmount is invalid", function () {
trustSet.LimitAmount = 1234;
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
"TrustSet: invalid LimitAmount"
);
});
it ('throws when QualityIn is not a number', () => {
trustSet.QualityIn = '1234'
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
'TrustSet: QualityIn must be a number'
)
})
it("throws when QualityIn is not a number", function () {
trustSet.QualityIn = "1234";
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
"TrustSet: QualityIn must be a number"
);
});
it ('throws when QualityOut is not a number', () => {
trustSet.QualityOut = '4321'
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
'TrustSet: QualityOut must be a number'
)
})
})
it("throws when QualityOut is not a number", function () {
trustSet.QualityOut = "4321";
assert.throws(
() => verifyTrustSet(trustSet),
ValidationError,
"TrustSet: QualityOut must be a number"
);
});
});

View File

@@ -1,29 +1,30 @@
import { isFlagEnabled } from '../../src/models/utils'
import { assert } from 'chai'
import { assert } from "chai";
import { isFlagEnabled } from "../../src/models/utils";
/**
* Utils Testing
* Utils Testing.
*
* Provides tests for utils used in models
* Provides tests for utils used in models.
*/
describe('Models Utils', () => {
describe('isFlagEnabled', () => {
let flags
const flag1 = 0x00010000
const flag2 = 0x00020000
describe("Models Utils", function () {
describe("isFlagEnabled", function () {
let flags;
const flag1 = 0x00010000;
const flag2 = 0x00020000;
beforeEach(() => {
flags = 0x00000000
})
beforeEach(function () {
flags = 0x00000000;
});
it('verifies a flag is enabled', () => {
flags += flag1 + flag2
assert.isTrue(isFlagEnabled(flags, flag1))
})
it("verifies a flag is enabled", function () {
flags += flag1 + flag2;
assert.isTrue(isFlagEnabled(flags, flag1));
});
it('verifies a flag is not enabled', () => {
flags += flag2
assert.isFalse(isFlagEnabled(flags, flag1))
})
})
})
it("verifies a flag is not enabled", function () {
flags += flag2;
assert.isFalse(isFlagEnabled(flags, flag1));
});
});
});

View File

@@ -1,79 +1,80 @@
import assert from 'assert'
import RangeSet from 'xrpl-local/client/rangeSet'
import assert from "assert";
describe('RangeSet', function () {
it('addRange()/addValue()', function () {
const r = new RangeSet()
import RangeSet from "xrpl-local/client/rangeSet";
r.addRange(4, 5)
r.addRange(7, 10)
r.addRange(1, 2)
r.addValue(3)
describe("RangeSet", function () {
it("addRange()/addValue()", function () {
const r = new RangeSet();
assert.deepEqual(r.serialize(), '1-5,7-10')
})
r.addRange(4, 5);
r.addRange(7, 10);
r.addRange(1, 2);
r.addValue(3);
it('addValue()/addRange() -- malformed', function () {
const r = new RangeSet()
assert.deepEqual(r.serialize(), "1-5,7-10");
});
it("addValue()/addRange() -- malformed", function () {
const r = new RangeSet();
assert.throws(function () {
r.addRange(2, 1)
})
})
r.addRange(2, 1);
});
});
it('parseAndAddRanges()', function () {
const r = new RangeSet()
r.parseAndAddRanges('4-5,7-10,1-2,3-3')
assert.deepEqual(r.serialize(), '1-5,7-10')
})
it('parseAndAddRanges() -- single ledger', function () {
const r = new RangeSet()
it("parseAndAddRanges()", function () {
const r = new RangeSet();
r.parseAndAddRanges("4-5,7-10,1-2,3-3");
assert.deepEqual(r.serialize(), "1-5,7-10");
});
it("parseAndAddRanges() -- single ledger", function () {
const r = new RangeSet();
r.parseAndAddRanges('3')
assert.strictEqual(r.serialize(), '3-3')
assert(r.containsValue(3))
assert(!r.containsValue(0))
assert(!r.containsValue(2))
assert(!r.containsValue(4))
assert(r.containsRange(3, 3))
assert(!r.containsRange(2, 3))
assert(!r.containsRange(3, 4))
r.parseAndAddRanges("3");
assert.strictEqual(r.serialize(), "3-3");
assert(r.containsValue(3));
assert(!r.containsValue(0));
assert(!r.containsValue(2));
assert(!r.containsValue(4));
assert(r.containsRange(3, 3));
assert(!r.containsRange(2, 3));
assert(!r.containsRange(3, 4));
r.parseAndAddRanges('1-5')
assert.strictEqual(r.serialize(), '1-5')
assert(r.containsValue(3))
assert(r.containsValue(1))
assert(r.containsValue(5))
assert(!r.containsValue(6))
assert(!r.containsValue(0))
assert(r.containsRange(1, 5))
assert(r.containsRange(2, 4))
assert(!r.containsRange(1, 6))
assert(!r.containsRange(0, 3))
})
r.parseAndAddRanges("1-5");
assert.strictEqual(r.serialize(), "1-5");
assert(r.containsValue(3));
assert(r.containsValue(1));
assert(r.containsValue(5));
assert(!r.containsValue(6));
assert(!r.containsValue(0));
assert(r.containsRange(1, 5));
assert(r.containsRange(2, 4));
assert(!r.containsRange(1, 6));
assert(!r.containsRange(0, 3));
});
it('containsValue()', function () {
const r = new RangeSet()
it("containsValue()", function () {
const r = new RangeSet();
r.addRange(32570, 11005146)
r.addValue(11005147)
r.addRange(32570, 11005146);
r.addValue(11005147);
assert.strictEqual(r.containsValue(1), false)
assert.strictEqual(r.containsValue(32569), false)
assert.strictEqual(r.containsValue(32570), true)
assert.strictEqual(r.containsValue(50000), true)
assert.strictEqual(r.containsValue(11005146), true)
assert.strictEqual(r.containsValue(11005147), true)
assert.strictEqual(r.containsValue(11005148), false)
assert.strictEqual(r.containsValue(12000000), false)
})
assert.strictEqual(r.containsValue(1), false);
assert.strictEqual(r.containsValue(32569), false);
assert.strictEqual(r.containsValue(32570), true);
assert.strictEqual(r.containsValue(50000), true);
assert.strictEqual(r.containsValue(11005146), true);
assert.strictEqual(r.containsValue(11005147), true);
assert.strictEqual(r.containsValue(11005148), false);
assert.strictEqual(r.containsValue(12000000), false);
});
it('reset()', function () {
const r = new RangeSet()
it("reset()", function () {
const r = new RangeSet();
r.addRange(4, 5)
r.addRange(7, 10)
r.reset()
r.addRange(4, 5);
r.addRange(7, 10);
r.reset();
assert.deepEqual(r.serialize(), '')
})
})
assert.deepEqual(r.serialize(), "");
});
});

View File

@@ -1,10 +1,11 @@
import setupClient from './setupClient'
import {Client} from 'xrpl-local'
import addresses from './fixtures/addresses.json'
import {getAllPublicMethods, loadTestSuites} from './testUtils'
import { Client } from "xrpl-local";
import addresses from "./fixtures/addresses.json";
import setupClient from "./setupClient";
import { getAllPublicMethods, loadTestSuites } from "./testUtils";
/**
* Client Test Runner
* Client Test Runner.
*
* Background: "test/api-test.ts" had hit 4000+ lines of test code and 300+
* individual tests. Additionally, a new address format was added which
@@ -21,62 +22,62 @@ import {getAllPublicMethods, loadTestSuites} from './testUtils'
* - Type the Client object under test and catch typing issues (currently untyped).
* - Sets the stage for more cleanup, like moving test-specific fixtures closer to their tests.
*/
describe('Client [Test Runner]', function () {
beforeEach(setupClient.setup)
afterEach(setupClient.teardown)
describe("Client [Test Runner]", function () {
beforeEach(setupClient.setup);
afterEach(setupClient.teardown);
// Collect all the tests:
const allPublicMethods = getAllPublicMethods(new Client("wss://"))
const allPublicMethods = getAllPublicMethods(new Client("wss://"));
// doesn't need the client, just needs to instantiate to get public methods
const allTestSuites = loadTestSuites()
const allTestSuites = loadTestSuites();
// Run all the tests:
for (const {name: methodName, tests, config} of allTestSuites) {
describe(`${methodName}`, () => {
for (const { name: methodName, tests, config } of allTestSuites) {
describe(`${methodName}`, function () {
// Run each test that does not use an address.
for (const [testName, fn] of tests) {
if (fn.length === 1) {
it(testName, function () {
return fn(this.client, addresses.ACCOUNT, this.mockRippled)
})
return fn(this.client, addresses.ACCOUNT, this.mockRippled);
});
}
}
// Run each test with a classic address.
describe(`[Classic Address]`, () => {
describe(`[Classic Address]`, function () {
for (const [testName, fn] of tests) {
if (fn.length >= 2) {
it(testName, function () {
return fn(this.client, addresses.ACCOUNT, this.mockRippled)
})
return fn(this.client, addresses.ACCOUNT, this.mockRippled);
});
}
}
})
});
// Run each test with an X-address.
if (!config.skipXAddress) {
describe(`[X-address]`, () => {
describe(`[X-address]`, function () {
for (const [testName, fn] of tests) {
if (fn.length >= 2) {
it(testName, function () {
return fn(this.client, addresses.ACCOUNT_X, this.mockRippled)
})
return fn(this.client, addresses.ACCOUNT_X, this.mockRippled);
});
}
}
})
});
}
})
});
}
// Report any missing tests.
const allTestedMethods = new Set(allTestSuites.map((s) => s.name))
const allTestedMethods = new Set(allTestSuites.map((s) => s.name));
for (const methodName of allPublicMethods) {
if (!allTestedMethods.has(methodName)) {
// TODO: Once migration is complete, remove `.skip()` so that missing tests are reported as failures.
it.skip(`${methodName} - no test suite found`, () => {
it.skip(`${methodName} - no test suite found`, function () {
throw new Error(
`Test file not found! Create file "test/client/${methodName}/index.ts".`
)
})
);
});
}
}
})
});

View File

@@ -1,181 +1,181 @@
import assert from 'assert-diff'
import _ from 'lodash'
import {Client} from 'xrpl-local'
import {RecursiveData} from 'xrpl-local/ledger/utils'
import {assertRejects} from './testUtils'
import addresses from './fixtures/addresses.json'
import setupClient from './setupClient'
import {toRippledAmount} from '../src'
import * as schemaValidator from 'xrpl-local/common/schema-validator'
import {validate} from 'xrpl-local/common'
import assert from "assert-diff";
import _ from "lodash";
import { Client } from "xrpl-local";
import { validate } from "xrpl-local/common";
import * as schemaValidator from "xrpl-local/common/schema-validator";
import {
RecursiveData,
renameCounterpartyToIssuerInOrder,
compareTransactions,
getRecursive
} from 'xrpl-local/ledger/utils'
getRecursive,
} from "xrpl-local/ledger/utils";
const address = addresses.ACCOUNT
assert.options.strict = true
import { toRippledAmount } from "../src";
import addresses from "./fixtures/addresses.json";
import setupClient from "./setupClient";
import { assertRejects } from "./testUtils";
const address = addresses.ACCOUNT;
assert.options.strict = true;
// how long before each test case times out
const TIMEOUT = 20000
const TIMEOUT = 20000;
describe('Client', function () {
this.timeout(TIMEOUT)
beforeEach(setupClient.setup)
afterEach(setupClient.teardown)
describe("Client", function () {
this.timeout(TIMEOUT);
beforeEach(setupClient.setup);
afterEach(setupClient.teardown);
it('Client - implicit server port', function () {
new Client('wss://s1.ripple.com')
})
it("Client - implicit server port", function () {
new Client("wss://s1.ripple.com");
});
it('Client invalid options', function () {
// @ts-ignore - This is intentionally invalid
assert.throws(() => new Client({invalid: true}))
})
it("Client invalid options", function () {
// @ts-expect-error - This is intentionally invalid
assert.throws(() => new Client({ invalid: true }));
});
it('Client valid options', function () {
const client = new Client('wss://s:1')
const privateConnectionUrl = (client.connection as any)._url
assert.deepEqual(privateConnectionUrl, 'wss://s:1')
})
it("Client valid options", function () {
const client = new Client("wss://s:1");
const privateConnectionUrl = (client.connection as any)._url;
assert.deepEqual(privateConnectionUrl, "wss://s:1");
});
it('Client invalid server uri', function () {
assert.throws(() => new Client('wss//s:1'))
})
it("Client invalid server uri", function () {
assert.throws(() => new Client("wss//s:1"));
});
it('Client connect() times out after 2 seconds', function () {
it("Client connect() times out after 2 seconds", function () {
// TODO: Use a timer mock like https://jestjs.io/docs/en/timer-mocks
// to test that connect() times out after 2 seconds.
})
});
describe('[private] schema-validator', function () {
it('valid', function () {
describe("[private] schema-validator", function () {
it("valid", function () {
assert.doesNotThrow(function () {
schemaValidator.schemaValidate(
'hash256',
'0F7ED9F40742D8A513AE86029462B7A6768325583DF8EE21B7EC663019DD6A0F'
)
})
})
"hash256",
"0F7ED9F40742D8A513AE86029462B7A6768325583DF8EE21B7EC663019DD6A0F"
);
});
});
it('invalid', function () {
it("invalid", function () {
assert.throws(function () {
schemaValidator.schemaValidate('hash256', 'invalid')
}, this.client.errors.ValidationError)
})
schemaValidator.schemaValidate("hash256", "invalid");
}, this.client.errors.ValidationError);
});
it('invalid - empty value', function () {
it("invalid - empty value", function () {
assert.throws(function () {
schemaValidator.schemaValidate('hash256', '')
}, this.client.errors.ValidationError)
})
schemaValidator.schemaValidate("hash256", "");
}, this.client.errors.ValidationError);
});
it('schema not found error', function () {
it("schema not found error", function () {
assert.throws(function () {
schemaValidator.schemaValidate('unexisting', 'anything')
}, /no schema/)
})
})
schemaValidator.schemaValidate("unexisting", "anything");
}, /no schema/);
});
});
describe('[private] validator', function () {
it('validateLedgerRange', function () {
describe("[private] validator", function () {
it("validateLedgerRange", function () {
const options = {
minLedgerVersion: 20000,
maxLedgerVersion: 10000
}
const thunk = _.partial(validate.getTransactions, {address, options})
assert.throws(thunk, this.client.errors.ValidationError)
maxLedgerVersion: 10000,
};
const thunk = _.partial(validate.getTransactions, { address, options });
assert.throws(thunk, this.client.errors.ValidationError);
assert.throws(
thunk,
/minLedgerVersion must not be greater than maxLedgerVersion/
)
})
);
});
it('secret', function () {
it("secret", function () {
function validateSecret(secret) {
validate.sign({txJSON: '', secret})
validate.sign({ txJSON: "", secret });
}
assert.doesNotThrow(
_.partial(validateSecret, 'shzjfakiK79YQdMjy4h8cGGfQSV6u')
)
_.partial(validateSecret, "shzjfakiK79YQdMjy4h8cGGfQSV6u")
);
assert.throws(
_.partial(validateSecret, 'shzjfakiK79YQdMjy4h8cGGfQSV6v'),
_.partial(validateSecret, "shzjfakiK79YQdMjy4h8cGGfQSV6v"),
this.client.errors.ValidationError
)
);
assert.throws(
_.partial(validateSecret, 1),
this.client.errors.ValidationError
)
);
assert.throws(
_.partial(validateSecret, ''),
_.partial(validateSecret, ""),
this.client.errors.ValidationError
)
);
assert.throws(
_.partial(validateSecret, 's!!!'),
_.partial(validateSecret, "s!!!"),
this.client.errors.ValidationError
)
);
assert.throws(
_.partial(validateSecret, 'passphrase'),
_.partial(validateSecret, "passphrase"),
this.client.errors.ValidationError
)
);
// 32 0s is a valid hex repr of seed bytes
const hex = new Array(33).join('0')
const hex = new Array(33).join("0");
assert.throws(
_.partial(validateSecret, hex),
this.client.errors.ValidationError
)
})
})
);
});
});
it('common utils - toRippledAmount', async () => {
const amount = {issuer: 'is', currency: 'c', value: 'v'}
it("common utils - toRippledAmount", async function () {
const amount = { issuer: "is", currency: "c", value: "v" };
assert.deepEqual(toRippledAmount(amount), {
issuer: 'is',
currency: 'c',
value: 'v'
})
})
issuer: "is",
currency: "c",
value: "v",
});
});
it('ledger utils - renameCounterpartyToIssuerInOrder', async () => {
it("ledger utils - renameCounterpartyToIssuerInOrder", async function () {
const order = {
taker_gets: {counterparty: '1', currency: 'XRP'},
taker_pays: {counterparty: '1', currency: 'XRP'}
}
taker_gets: { counterparty: "1", currency: "XRP" },
taker_pays: { counterparty: "1", currency: "XRP" },
};
const expected = {
taker_gets: {issuer: '1', currency: 'XRP'},
taker_pays: {issuer: '1', currency: 'XRP'}
}
assert.deepEqual(
renameCounterpartyToIssuerInOrder(order),
expected
)
})
taker_gets: { issuer: "1", currency: "XRP" },
taker_pays: { issuer: "1", currency: "XRP" },
};
assert.deepEqual(renameCounterpartyToIssuerInOrder(order), expected);
});
it('ledger utils - compareTransactions', async () => {
// @ts-ignore
assert.strictEqual(compareTransactions({}, {}), 0)
let first: any = {outcome: {ledgerVersion: 1, indexInLedger: 100}}
let second: any = {outcome: {ledgerVersion: 1, indexInLedger: 200}}
assert.strictEqual(compareTransactions(first, second), -1)
first = {outcome: {ledgerVersion: 1, indexInLedger: 100}}
second = {outcome: {ledgerVersion: 1, indexInLedger: 100}}
assert.strictEqual(compareTransactions(first, second), 0)
first = {outcome: {ledgerVersion: 1, indexInLedger: 200}}
second = {outcome: {ledgerVersion: 1, indexInLedger: 100}}
assert.strictEqual(compareTransactions(first, second), 1)
})
it("ledger utils - compareTransactions", async function () {
// @ts-expect-error
assert.strictEqual(compareTransactions({}, {}), 0);
let first: any = { outcome: { ledgerVersion: 1, indexInLedger: 100 } };
let second: any = { outcome: { ledgerVersion: 1, indexInLedger: 200 } };
assert.strictEqual(compareTransactions(first, second), -1);
first = { outcome: { ledgerVersion: 1, indexInLedger: 100 } };
second = { outcome: { ledgerVersion: 1, indexInLedger: 100 } };
assert.strictEqual(compareTransactions(first, second), 0);
first = { outcome: { ledgerVersion: 1, indexInLedger: 200 } };
second = { outcome: { ledgerVersion: 1, indexInLedger: 100 } };
assert.strictEqual(compareTransactions(first, second), 1);
});
it('ledger utils - getRecursive', async () => {
it("ledger utils - getRecursive", async function () {
function getter(marker) {
return new Promise<RecursiveData>((resolve, reject) => {
if (marker != null) {
reject(new Error())
return
reject(new Error());
return;
}
resolve({marker: 'A', results: [1]})
})
resolve({ marker: "A", results: [1] });
});
}
await assertRejects(getRecursive(getter, 10), Error)
})
})
await assertRejects(getRecursive(getter, 10), Error);
});
});

View File

@@ -1,41 +1,36 @@
import {Client, BroadcastClient} from 'xrpl-local'
import {createMockRippled} from './mockRippled'
import {getFreePort} from './testUtils'
import { Client, BroadcastClient } from "xrpl-local";
import { createMockRippled } from "./mockRippled";
import { getFreePort } from "./testUtils";
function setupMockRippledConnection(testcase, port) {
return new Promise<void>((resolve, reject) => {
testcase.mockRippled = createMockRippled(port)
testcase._mockedServerPort = port
testcase.client = new Client('ws://localhost:' + port)
testcase.client
.connect()
.then(resolve)
.catch(reject)
})
testcase.mockRippled = createMockRippled(port);
testcase._mockedServerPort = port;
testcase.client = new Client(`ws://localhost:${port}`);
testcase.client.connect().then(resolve).catch(reject);
});
}
function setupMockRippledConnectionForBroadcast(testcase, ports) {
return new Promise<void>((resolve, reject) => {
const servers = ports.map((port) => 'ws://localhost:' + port)
testcase.mocks = ports.map((port) => createMockRippled(port))
testcase.client = new BroadcastClient(servers)
testcase.client
.connect()
.then(resolve)
.catch(reject)
})
const servers = ports.map((port) => `ws://localhost:${port}`);
testcase.mocks = ports.map((port) => createMockRippled(port));
testcase.client = new BroadcastClient(servers);
testcase.client.connect().then(resolve).catch(reject);
});
}
function setup(this: any) {
return getFreePort().then((port) => {
return setupMockRippledConnection(this, port)
})
return setupMockRippledConnection(this, port);
});
}
function setupBroadcast(this: any) {
return Promise.all([getFreePort(), getFreePort()]).then((ports) => {
return setupMockRippledConnectionForBroadcast(this, ports)
})
return setupMockRippledConnectionForBroadcast(this, ports);
});
}
function teardown(this: any, done) {
@@ -43,18 +38,18 @@ function teardown(this: any, done) {
.disconnect()
.then(() => {
if (this.mockRippled != null) {
this.mockRippled.close()
this.mockRippled.close();
} else {
this.mocks.forEach((mock) => mock.close())
this.mocks.forEach((mock) => mock.close());
}
setImmediate(done)
setImmediate(done);
})
.catch(done)
.catch(done);
}
export default {
setup: setup,
teardown: teardown,
setupBroadcast: setupBroadcast,
createMockRippled: createMockRippled
}
setup,
teardown,
setupBroadcast,
createMockRippled,
};

View File

@@ -1,55 +1,46 @@
import {Client, BroadcastClient} from 'xrpl-local'
import { Client, BroadcastClient } from "xrpl-local";
const port = 34371
const baseUrl = 'ws://testripple.circleci.com:'
const port = 34371;
const baseUrl = "ws://testripple.circleci.com:";
function setup(this: any, port_ = port) {
const tclient = new Client(baseUrl + port_)
const tclient = new Client(baseUrl + port_);
return tclient
.connect()
.then(() => {
return tclient.connection.request({
// TODO: resolve when we redo the testing framework
// @ts-ignore
command: 'test_command',
data: {openOnOtherPort: true}
})
command: "test_command",
data: { openOnOtherPort: true },
});
})
.then((got) => {
return new Promise<void>((resolve, reject) => {
// @ts-ignore
this.client = new Client(baseUrl + got.port)
this.client
.connect()
.then(resolve)
.catch(reject)
})
this.client = new Client(baseUrl + got.port);
this.client.connect().then(resolve).catch(reject);
});
})
.then(() => {
return tclient.disconnect()
})
return tclient.disconnect();
});
}
function setupBroadcast(this: any) {
const servers = [port, port + 1].map((port_) => baseUrl + port_)
this.client = new BroadcastClient(servers)
const servers = [port, port + 1].map((port_) => baseUrl + port_);
this.client = new BroadcastClient(servers);
return new Promise<void>((resolve, reject) => {
this.client
.connect()
.then(resolve)
.catch(reject)
})
this.client.connect().then(resolve).catch(reject);
});
}
function teardown(this: any) {
if (this.client.isConnected()) {
return this.client.disconnect()
return this.client.disconnect();
}
return undefined
return undefined;
}
export default {
setup: setup,
teardown: teardown,
setupBroadcast: setupBroadcast
}
setup,
teardown,
setupBroadcast,
};

View File

@@ -1,59 +1,63 @@
import assert from 'assert'
import {SHAMap, NodeType} from '../src/utils/hashes/shamap'
const TYPE_TRANSACTION_NO_METADATA = NodeType.TRANSACTION_NO_METADATA
import assert from "assert";
var HEX_ZERO =
'00000000000000000000000000000000' + '00000000000000000000000000000000'
import { SHAMap, NodeType } from "../src/utils/hashes/shamap";
const TYPE_TRANSACTION_NO_METADATA = NodeType.TRANSACTION_NO_METADATA;
const HEX_ZERO =
"00000000000000000000000000000000" + "00000000000000000000000000000000";
/**
* Generates data to hash for testing
* Generates data to hash for testing.
*
* @param v
*/
function intToVuc(v: number): string {
var ret = ''
let ret = "";
for (var i = 0; i < 32; i++) {
ret += '0'
ret += v.toString(16).toUpperCase()
for (let i = 0; i < 32; i++) {
ret += "0";
ret += v.toString(16).toUpperCase();
}
return ret
return ret;
}
function fillShamapTest(shamap: any, keys: string[], hashes: string[]) {
for (var i = 0; i < keys.length; i++) {
var data = intToVuc(i)
shamap.addItem(keys[i].toUpperCase(), data, TYPE_TRANSACTION_NO_METADATA)
assert.equal(shamap.hash, hashes[i])
for (let i = 0; i < keys.length; i++) {
const data = intToVuc(i);
shamap.addItem(keys[i].toUpperCase(), data, TYPE_TRANSACTION_NO_METADATA);
assert.equal(shamap.hash, hashes[i]);
}
}
describe('SHAMap', function () {
describe('#addItem', function () {
it('will add new nodes to v1', function () {
var keys = [
'b92891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8',
'b92881fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8',
'b92691fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8',
'b92791fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8',
'b91891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8',
'b99891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8',
'f22891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8',
'292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8'
]
describe("SHAMap", function () {
describe("#addItem", function () {
it("will add new nodes to v1", function () {
const keys = [
"b92891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
"b92881fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
"b92691fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
"b92791fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
"b91891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
"b99891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
"f22891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
"292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8",
];
var hashesv1 = [
'B7387CFEA0465759ADC718E8C42B52D2309D179B326E239EB5075C64B6281F7F',
'FBC195A9592A54AB44010274163CB6BA95F497EC5BA0A8831845467FB2ECE266',
'4E7D2684B65DFD48937FFB775E20175C43AF0C94066F7D5679F51AE756795B75',
'7A2F312EB203695FFD164E038E281839EEF06A1B99BFC263F3CECC6C74F93E07',
'395A6691A372387A703FB0F2C6D2C405DAF307D0817F8F0E207596462B0E3A3E',
'D044C0A696DE3169CC70AE216A1564D69DE96582865796142CE7D98A84D9DDE4',
'76DCC77C4027309B5A91AD164083264D70B77B5E43E08AEDA5EBF94361143615',
'DF4220E93ADC6F5569063A01B4DC79F8DB9553B6A3222ADE23DEA02BBE7230E5'
]
const hashesv1 = [
"B7387CFEA0465759ADC718E8C42B52D2309D179B326E239EB5075C64B6281F7F",
"FBC195A9592A54AB44010274163CB6BA95F497EC5BA0A8831845467FB2ECE266",
"4E7D2684B65DFD48937FFB775E20175C43AF0C94066F7D5679F51AE756795B75",
"7A2F312EB203695FFD164E038E281839EEF06A1B99BFC263F3CECC6C74F93E07",
"395A6691A372387A703FB0F2C6D2C405DAF307D0817F8F0E207596462B0E3A3E",
"D044C0A696DE3169CC70AE216A1564D69DE96582865796142CE7D98A84D9DDE4",
"76DCC77C4027309B5A91AD164083264D70B77B5E43E08AEDA5EBF94361143615",
"DF4220E93ADC6F5569063A01B4DC79F8DB9553B6A3222ADE23DEA02BBE7230E5",
];
var shamapv1 = new SHAMap()
assert.equal(shamapv1.hash, HEX_ZERO)
fillShamapTest(shamapv1, keys, hashesv1)
})
})
})
const shamapv1 = new SHAMap();
assert.equal(shamapv1.hash, HEX_ZERO);
fillShamapTest(shamapv1, keys, hashesv1);
});
});
});

View File

@@ -1,9 +1,11 @@
import net from 'net'
import _ from 'lodash'
import fs from 'fs'
import path from 'path'
import {Client} from 'xrpl-local'
import assert from 'assert-diff'
import fs from "fs";
import net from "net";
import path from "path";
import assert from "assert-diff";
import _ from "lodash";
import { Client } from "xrpl-local";
/**
* The test function. It takes a Client object and then some other data to
@@ -14,13 +16,13 @@ export type TestFn = (
client: Client,
address: string,
mockRippled?: any
) => void | PromiseLike<void>
) => void | PromiseLike<void>;
/**
* A suite of tests to run. Maps the test name to the test function.
*/
export interface TestSuite {
[testName: string]: TestFn
[testName: string]: TestFn;
}
/**
@@ -30,17 +32,21 @@ export interface TestSuite {
* so that we can report it.
*/
interface LoadedTestSuite {
name: string
tests: [string, TestFn][]
name: string;
tests: Array<[string, TestFn]>;
config: {
/** Set to true to skip re-running tests with an X-address. */
skipXAddress?: boolean
}
skipXAddress?: boolean;
};
}
/**
* Check the response against the expected result. Optionally validate
* that response against a given schema as well.
*
* @param response - Response received from the method.
* @param expected - Expected response from the method.
* @param schemaName - Name of the schema used to validate the shape of the response.
*/
export function assertResultMatch(
response: any,
@@ -48,29 +54,33 @@ export function assertResultMatch(
schemaName?: string
) {
if (expected.txJSON) {
assert(response.txJSON)
assert(response.txJSON);
assert.deepEqual(
JSON.parse(response.txJSON),
JSON.parse(expected.txJSON),
'checkResult: txJSON must match'
)
"checkResult: txJSON must match"
);
}
if (expected.tx_json) {
assert(response.tx_json)
assert(response.tx_json);
assert.deepEqual(
response.tx_json,
expected.tx_json,
'checkResult: tx_json must match'
)
"checkResult: tx_json must match"
);
}
assert.deepEqual(
_.omit(response, ['txJSON', 'tx_json']),
_.omit(expected, ['txJSON', 'tx_json'])
)
_.omit(response, ["txJSON", "tx_json"]),
_.omit(expected, ["txJSON", "tx_json"])
);
}
/**
* Check that the promise rejects with an expected error.
*
* @param promise - The promise returned by the method.
* @param instanceOf - Expected error type that the method will throw.
* @param message - Expected error message/substring of the error message.
*/
export async function assertRejects(
promise: PromiseLike<any>,
@@ -78,14 +88,14 @@ export async function assertRejects(
message?: string | RegExp
) {
try {
await promise
assert(false, 'Expected an error to be thrown')
await promise;
assert(false, "Expected an error to be thrown");
} catch (error) {
assert(error instanceof instanceOf, error.message)
if (typeof message === 'string') {
assert.strictEqual(error.message, message)
assert(error instanceof instanceOf, error.message);
if (typeof message === "string") {
assert.strictEqual(error.message, message);
} else if (message instanceof RegExp) {
assert(message.test(error.message))
assert(message.test(error.message));
}
}
}
@@ -93,61 +103,63 @@ export async function assertRejects(
// using a free port instead of a constant port enables parallelization
export function getFreePort() {
return new Promise((resolve, reject) => {
const server = net.createServer()
let port
server.on('listening', function () {
port = (server.address() as any).port
server.close()
})
server.on('close', function () {
resolve(port)
})
server.on('error', function (error) {
reject(error)
})
server.listen(0)
})
const server = net.createServer();
let port;
server.on("listening", function () {
port = (server.address() as any).port;
server.close();
});
server.on("close", function () {
resolve(port);
});
server.on("error", function (error) {
reject(error);
});
server.listen(0);
});
}
export function getAllPublicMethods(client: Client) {
return Array.from(
new Set([
...Object.getOwnPropertyNames(client),
...Object.getOwnPropertyNames(Client.prototype)
...Object.getOwnPropertyNames(Client.prototype),
])
).filter((key) => !key.startsWith('_'))
).filter((key) => !key.startsWith("_"));
}
export function loadTestSuites(): LoadedTestSuite[] {
const allTests = fs.readdirSync(path.join(__dirname, 'client'), {
encoding: 'utf8'
})
const allTests: any[] = fs.readdirSync(path.join(__dirname, "client"), {
encoding: "utf8",
});
return allTests
.map((methodName) => {
if (methodName.startsWith('.DS_Store')) {
return null
if (methodName.startsWith(".DS_Store")) {
return null;
}
if (methodName.endsWith('.ts')) {
methodName = methodName.slice(0, -3)
if (methodName.endsWith(".ts")) {
methodName = methodName.slice(0, -3);
}
const testSuite = require(`./client/${methodName}`)
const testSuite = require(`./client/${methodName}`);
return {
name: methodName,
config: testSuite.config || {},
tests: Object.entries(testSuite.default || {})
} as LoadedTestSuite
tests: Object.entries(testSuite.default || {}),
} as LoadedTestSuite;
})
.filter(Boolean)
.filter(Boolean) as LoadedTestSuite[];
}
/**
* Ignore WebSocket DisconnectErrors. Useful for making requests where we don't
* care about the response and plan to teardown the test before the response
* has come back.
*
* @param error - Thrown error.
*/
export function ignoreWebSocketDisconnect(error: Error): void {
if (error.message === 'websocket was closed') {
return
if (error.message === "websocket was closed") {
return;
}
throw error
}
throw error;
}

View File

@@ -1,3 +0,0 @@
{
"extends": "../tsconfig-base.json",
}

View File

@@ -1,147 +1,147 @@
import assert from 'assert-diff'
import {computeLedgerHeaderHash} from '../../src/utils'
import {ValidationError} from '../../src/common/errors'
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import {assertResultMatch} from '../testUtils'
const {computeLedgerHash: REQUEST_FIXTURES} = requests
import assert from "assert-diff";
import { ValidationError } from "../../src/common/errors";
import { computeLedgerHeaderHash } from "../../src/utils";
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import { assertResultMatch } from "../testUtils";
const { computeLedgerHash: REQUEST_FIXTURES } = requests;
function getNewLedger() {
return JSON.parse(JSON.stringify(responses.getLedger.full))
return JSON.parse(JSON.stringify(responses.getLedger.full));
}
describe('Compute Ledger Hash', function () {
it('given corrupt data - should fail', () => {
const ledger = getNewLedger()
// @ts-ignore - Change Amount to 12000000000
describe("Compute Ledger Hash", function () {
it("given corrupt data - should fail", function () {
const ledger = getNewLedger();
ledger.transactions[0].rawTransaction =
'{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Amount":"12000000000","Destination":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Fee":"10","Flags":0,"Sequence":62,"SigningPubKey":"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E","TransactionType":"Payment","TxnSignature":"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639","hash":"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF","meta":{"AffectedNodes":[{"CreatedNode":{"LedgerEntryType":"AccountRoot","LedgerIndex":"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E","NewFields":{"Account":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Balance":"10000000000","Sequence":1}}},{"ModifiedNode":{"FinalFields":{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Balance":"981481999380","Flags":0,"OwnerCount":0,"Sequence":63},"LedgerEntryType":"AccountRoot","LedgerIndex":"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A","PreviousFields":{"Balance":"991481999390","Sequence":62},"PreviousTxnID":"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F","PreviousTxnLgrSeq":31317}}],"TransactionIndex":0,"TransactionResult":"tesSUCCESS"},"ledger_index":38129}'
ledger.parentCloseTime = ledger.closeTime
let hash
'{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Amount":"12000000000","Destination":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Fee":"10","Flags":0,"Sequence":62,"SigningPubKey":"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E","TransactionType":"Payment","TxnSignature":"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639","hash":"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF","meta":{"AffectedNodes":[{"CreatedNode":{"LedgerEntryType":"AccountRoot","LedgerIndex":"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E","NewFields":{"Account":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Balance":"10000000000","Sequence":1}}},{"ModifiedNode":{"FinalFields":{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Balance":"981481999380","Flags":0,"OwnerCount":0,"Sequence":63},"LedgerEntryType":"AccountRoot","LedgerIndex":"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A","PreviousFields":{"Balance":"991481999390","Sequence":62},"PreviousTxnID":"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F","PreviousTxnLgrSeq":31317}}],"TransactionIndex":0,"TransactionResult":"tesSUCCESS"},"ledger_index":38129}';
ledger.parentCloseTime = ledger.closeTime;
let hash;
try {
hash = computeLedgerHeaderHash(ledger, {computeTreeHashes: true})
hash = computeLedgerHeaderHash(ledger, { computeTreeHashes: true });
} catch (error) {
assert(error instanceof ValidationError)
assert(error instanceof ValidationError);
assert.strictEqual(
error.message,
'transactionHash in header does not match computed hash of transactions'
)
"transactionHash in header does not match computed hash of transactions"
);
assert.deepStrictEqual(error.data, {
transactionHashInHeader:
'DB83BF807416C5B3499A73130F843CF615AB8E797D79FE7D330ADF1BFA93951A',
"DB83BF807416C5B3499A73130F843CF615AB8E797D79FE7D330ADF1BFA93951A",
computedHashOfTransactions:
'EAA1ADF4D627339450F0E95EA88B7069186DD64230BAEBDCF3EEC4D616A9FC68'
})
return
"EAA1ADF4D627339450F0E95EA88B7069186DD64230BAEBDCF3EEC4D616A9FC68",
});
return;
}
assert(
false,
'Should throw ValidationError instead of producing hash: ' + hash
)
})
`Should throw ValidationError instead of producing hash: ${hash}`
);
});
it('given ledger without raw transactions - should throw', () => {
const ledger = getNewLedger()
// @ts-ignore - Delete rawTransaction
delete ledger.transactions[0].rawTransaction
ledger.parentCloseTime = ledger.closeTime
let hash
it("given ledger without raw transactions - should throw", function () {
const ledger = getNewLedger();
delete ledger.transactions[0].rawTransaction;
ledger.parentCloseTime = ledger.closeTime;
let hash;
try {
hash = computeLedgerHeaderHash(ledger, {computeTreeHashes: true})
hash = computeLedgerHeaderHash(ledger, { computeTreeHashes: true });
} catch (error) {
assert(error instanceof ValidationError)
assert(error instanceof ValidationError);
assert.strictEqual(
error.message,
'ledger' + ' is missing raw transactions'
)
return
"ledger" + " is missing raw transactions"
);
return;
}
assert(
false,
'Should throw ValidationError instead of producing hash: ' + hash
)
})
`Should throw ValidationError instead of producing hash: ${hash}`
);
});
it('given ledger without state or transactions - only compute ledger hash', () => {
const ledger = getNewLedger()
it("given ledger without state or transactions - only compute ledger hash", function () {
const ledger = getNewLedger();
assert.strictEqual(
// @ts-ignore
ledger.transactions[0].rawTransaction,
'{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Amount":"10000000000","Destination":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Fee":"10","Flags":0,"Sequence":62,"SigningPubKey":"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E","TransactionType":"Payment","TxnSignature":"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639","hash":"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF","meta":{"AffectedNodes":[{"CreatedNode":{"LedgerEntryType":"AccountRoot","LedgerIndex":"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E","NewFields":{"Account":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Balance":"10000000000","Sequence":1}}},{"ModifiedNode":{"FinalFields":{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Balance":"981481999380","Flags":0,"OwnerCount":0,"Sequence":63},"LedgerEntryType":"AccountRoot","LedgerIndex":"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A","PreviousFields":{"Balance":"991481999390","Sequence":62},"PreviousTxnID":"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F","PreviousTxnLgrSeq":31317}}],"TransactionIndex":0,"TransactionResult":"tesSUCCESS"},"ledger_index":38129}'
)
ledger.parentCloseTime = ledger.closeTime
const computeLedgerHash = computeLedgerHeaderHash
);
ledger.parentCloseTime = ledger.closeTime;
const computeLedgerHash = computeLedgerHeaderHash;
function testCompute(ledger, expectedError) {
let hash = computeLedgerHash(ledger)
let hash = computeLedgerHash(ledger);
assert.strictEqual(
hash,
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E'
)
"E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E"
);
// fail if required to compute tree hashes
try {
hash = computeLedgerHash(ledger, {computeTreeHashes: true})
hash = computeLedgerHash(ledger, { computeTreeHashes: true });
} catch (error) {
assert(error instanceof ValidationError)
assert.strictEqual(error.message, expectedError)
return
assert(error instanceof ValidationError);
assert.strictEqual(error.message, expectedError);
return;
}
assert(
false,
'Should throw ValidationError instead of producing hash: ' + hash
)
`Should throw ValidationError instead of producing hash: ${hash}`
);
}
const transactions = ledger.transactions
delete ledger.transactions
testCompute(ledger, 'transactions property is missing from the ledger')
delete ledger.rawState
testCompute(ledger, 'transactions property is missing from the ledger')
ledger.transactions = transactions
testCompute(ledger, 'rawState property is missing from the ledger')
})
const transactions = ledger.transactions;
delete ledger.transactions;
testCompute(ledger, "transactions property is missing from the ledger");
delete ledger.rawState;
testCompute(ledger, "transactions property is missing from the ledger");
ledger.transactions = transactions;
testCompute(ledger, "rawState property is missing from the ledger");
});
it('wrong hash', () => {
const ledger = getNewLedger()
assertResultMatch(ledger, responses.getLedger.full, 'getLedger')
it("wrong hash", function () {
const ledger = getNewLedger();
assertResultMatch(ledger, responses.getLedger.full, "getLedger");
const newLedger = {
...ledger,
parentCloseTime: ledger.closeTime,
stateHash:
'D9ABF622DA26EEEE48203085D4BC23B0F77DC6F8724AC33D975DA3CA492D2E44'
}
"D9ABF622DA26EEEE48203085D4BC23B0F77DC6F8724AC33D975DA3CA492D2E44",
};
assert.throws(() => {
computeLedgerHeaderHash(newLedger)
}, /does not match computed hash of state/)
})
computeLedgerHeaderHash(newLedger);
}, /does not match computed hash of state/);
});
it('computeLedgerHash', () => {
const header = REQUEST_FIXTURES.header
const ledgerHash = computeLedgerHeaderHash(header)
it("computeLedgerHash", function () {
const header = REQUEST_FIXTURES.header;
const ledgerHash = computeLedgerHeaderHash(header);
assert.strictEqual(
ledgerHash,
'F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349'
)
})
"F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349"
);
});
it('computeLedgerHash - with transactions', () => {
it("computeLedgerHash - with transactions", function () {
const header = {
...REQUEST_FIXTURES.header,
transactionHash: undefined,
rawTransactions: JSON.stringify(REQUEST_FIXTURES.transactions)
}
const ledgerHash = computeLedgerHeaderHash(header)
rawTransactions: JSON.stringify(REQUEST_FIXTURES.transactions),
};
const ledgerHash = computeLedgerHeaderHash(header);
assert.strictEqual(
ledgerHash,
'F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349'
)
})
"F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349"
);
});
it('computeLedgerHash - incorrent transaction_hash', () => {
const header = Object.assign({}, REQUEST_FIXTURES.header, {
it("computeLedgerHash - incorrent transaction_hash", function () {
const header = {
...REQUEST_FIXTURES.header,
transactionHash:
'325EACC5271322539EEEC2D6A5292471EF1B3E72AE7180533EFC3B8F0AD435C9'
})
header.rawTransactions = JSON.stringify(REQUEST_FIXTURES.transactions)
assert.throws(() => computeLedgerHeaderHash(header))
})
})
"325EACC5271322539EEEC2D6A5292471EF1B3E72AE7180533EFC3B8F0AD435C9",
};
header.rawTransactions = JSON.stringify(REQUEST_FIXTURES.transactions);
assert.throws(() => computeLedgerHeaderHash(header));
});
});

View File

@@ -1,123 +1,124 @@
import assert from 'assert-diff'
import BigNumber from 'bignumber.js'
import {dropsToXrp} from '../../src/utils'
import assert from "assert-diff";
import BigNumber from "bignumber.js";
describe('Drops To XRP', function () {
it('works with a typical amount', () => {
const xrp = dropsToXrp('2000000')
assert.strictEqual(xrp, '2', '2 million drops equals 2 XRP')
})
import { dropsToXrp } from "../../src/utils";
it('works with fractions', () => {
let xrp = dropsToXrp('3456789')
assert.strictEqual(xrp, '3.456789', '3,456,789 drops equals 3.456789 XRP')
describe("Drops To XRP", function () {
it("works with a typical amount", function () {
const xrp = dropsToXrp("2000000");
assert.strictEqual(xrp, "2", "2 million drops equals 2 XRP");
});
xrp = dropsToXrp('3400000')
assert.strictEqual(xrp, '3.4', '3,400,000 drops equals 3.4 XRP')
it("works with fractions", function () {
let xrp = dropsToXrp("3456789");
assert.strictEqual(xrp, "3.456789", "3,456,789 drops equals 3.456789 XRP");
xrp = dropsToXrp('1')
assert.strictEqual(xrp, '0.000001', '1 drop equals 0.000001 XRP')
xrp = dropsToXrp("3400000");
assert.strictEqual(xrp, "3.4", "3,400,000 drops equals 3.4 XRP");
xrp = dropsToXrp('1.0')
assert.strictEqual(xrp, '0.000001', '1.0 drops equals 0.000001 XRP')
xrp = dropsToXrp("1");
assert.strictEqual(xrp, "0.000001", "1 drop equals 0.000001 XRP");
xrp = dropsToXrp('1.00')
assert.strictEqual(xrp, '0.000001', '1.00 drops equals 0.000001 XRP')
})
xrp = dropsToXrp("1.0");
assert.strictEqual(xrp, "0.000001", "1.0 drops equals 0.000001 XRP");
it('works with zero', () => {
let xrp = dropsToXrp('0')
assert.strictEqual(xrp, '0', '0 drops equals 0 XRP')
xrp = dropsToXrp("1.00");
assert.strictEqual(xrp, "0.000001", "1.00 drops equals 0.000001 XRP");
});
it("works with zero", function () {
let xrp = dropsToXrp("0");
assert.strictEqual(xrp, "0", "0 drops equals 0 XRP");
// negative zero is equivalent to zero
xrp = dropsToXrp('-0')
assert.strictEqual(xrp, '0', '-0 drops equals 0 XRP')
xrp = dropsToXrp("-0");
assert.strictEqual(xrp, "0", "-0 drops equals 0 XRP");
xrp = dropsToXrp('0.00')
assert.strictEqual(xrp, '0', '0.00 drops equals 0 XRP')
xrp = dropsToXrp("0.00");
assert.strictEqual(xrp, "0", "0.00 drops equals 0 XRP");
xrp = dropsToXrp('000000000')
assert.strictEqual(xrp, '0', '000000000 drops equals 0 XRP')
})
xrp = dropsToXrp("000000000");
assert.strictEqual(xrp, "0", "000000000 drops equals 0 XRP");
});
it('works with a negative value', () => {
const xrp = dropsToXrp('-2000000')
assert.strictEqual(xrp, '-2', '-2 million drops equals -2 XRP')
})
it("works with a negative value", function () {
const xrp = dropsToXrp("-2000000");
assert.strictEqual(xrp, "-2", "-2 million drops equals -2 XRP");
});
it('works with a value ending with a decimal point', () => {
let xrp = dropsToXrp('2000000.')
assert.strictEqual(xrp, '2', '2000000. drops equals 2 XRP')
it("works with a value ending with a decimal point", function () {
let xrp = dropsToXrp("2000000.");
assert.strictEqual(xrp, "2", "2000000. drops equals 2 XRP");
xrp = dropsToXrp('-2000000.')
assert.strictEqual(xrp, '-2', '-2000000. drops equals -2 XRP')
})
xrp = dropsToXrp("-2000000.");
assert.strictEqual(xrp, "-2", "-2000000. drops equals -2 XRP");
});
it('works with BigNumber objects', () => {
let xrp = dropsToXrp(new BigNumber(2000000))
assert.strictEqual(xrp, '2', '(BigNumber) 2 million drops equals 2 XRP')
it("works with BigNumber objects", function () {
let xrp = dropsToXrp(new BigNumber(2000000));
assert.strictEqual(xrp, "2", "(BigNumber) 2 million drops equals 2 XRP");
xrp = dropsToXrp(new BigNumber(-2000000))
assert.strictEqual(xrp, '-2', '(BigNumber) -2 million drops equals -2 XRP')
xrp = dropsToXrp(new BigNumber(-2000000));
assert.strictEqual(xrp, "-2", "(BigNumber) -2 million drops equals -2 XRP");
xrp = dropsToXrp(new BigNumber(2345678))
xrp = dropsToXrp(new BigNumber(2345678));
assert.strictEqual(
xrp,
'2.345678',
'(BigNumber) 2,345,678 drops equals 2.345678 XRP'
)
"2.345678",
"(BigNumber) 2,345,678 drops equals 2.345678 XRP"
);
xrp = dropsToXrp(new BigNumber(-2345678))
xrp = dropsToXrp(new BigNumber(-2345678));
assert.strictEqual(
xrp,
'-2.345678',
'(BigNumber) -2,345,678 drops equals -2.345678 XRP'
)
})
"-2.345678",
"(BigNumber) -2,345,678 drops equals -2.345678 XRP"
);
});
it('works with a number', () => {
it("works with a number", function () {
// This is not recommended. Use strings or BigNumber objects to avoid precision errors.
let xrp = dropsToXrp(2000000)
assert.strictEqual(xrp, '2', '(number) 2 million drops equals 2 XRP')
xrp = dropsToXrp(-2000000)
assert.strictEqual(xrp, '-2', '(number) -2 million drops equals -2 XRP')
})
let xrp = dropsToXrp(2000000);
assert.strictEqual(xrp, "2", "(number) 2 million drops equals 2 XRP");
xrp = dropsToXrp(-2000000);
assert.strictEqual(xrp, "-2", "(number) -2 million drops equals -2 XRP");
});
it('throws with an amount with too many decimal places', () => {
it("throws with an amount with too many decimal places", function () {
assert.throws(() => {
dropsToXrp('1.2')
}, /has too many decimal places/)
dropsToXrp("1.2");
}, /has too many decimal places/);
assert.throws(() => {
dropsToXrp('0.10')
}, /has too many decimal places/)
})
dropsToXrp("0.10");
}, /has too many decimal places/);
});
it('throws with an invalid value', () => {
it("throws with an invalid value", function () {
assert.throws(() => {
dropsToXrp('FOO')
}, /invalid value/)
dropsToXrp("FOO");
}, /invalid value/);
assert.throws(() => {
dropsToXrp('1e-7')
}, /invalid value/)
dropsToXrp("1e-7");
}, /invalid value/);
assert.throws(() => {
dropsToXrp('2,0')
}, /invalid value/)
dropsToXrp("2,0");
}, /invalid value/);
assert.throws(() => {
dropsToXrp('.')
}, /dropsToXrp: invalid value '\.', should be a BigNumber or string-encoded number\./)
})
dropsToXrp(".");
}, /dropsToXrp: invalid value '\.', should be a BigNumber or string-encoded number\./);
});
it('throws with an amount more than one decimal point', () => {
it("throws with an amount more than one decimal point", function () {
assert.throws(() => {
dropsToXrp('1.0.0')
}, /dropsToXrp: invalid value '1\.0\.0'/)
dropsToXrp("1.0.0");
}, /dropsToXrp: invalid value '1\.0\.0'/);
assert.throws(() => {
dropsToXrp('...')
}, /dropsToXrp: invalid value '\.\.\.'/)
})
})
dropsToXrp("...");
}, /dropsToXrp: invalid value '\.\.\.'/);
});
});

View File

@@ -1,231 +1,247 @@
import assert from 'assert-diff'
import responses from '../fixtures/responses'
import {generateXAddress, GenerateAddressOptions} from '../../src/utils/generateAddress'
import ECDSA from '../../src/common/ecdsa'
import {UnexpectedError} from '../../src/common/errors'
import assert from "assert-diff";
describe('Generate Address', function () {
it('generateAddress', () => {
import ECDSA from "../../src/common/ecdsa";
import { UnexpectedError } from "../../src/common/errors";
import {
generateXAddress,
GenerateAddressOptions,
} from "../../src/utils/generateAddress";
import responses from "../fixtures/responses";
describe("Generate Address", function () {
it("generateAddress", function () {
// GIVEN entropy of all zeros
function random() {
return new Array(16).fill(0)
return new Array(16).fill(0);
}
assert.deepEqual(
// WHEN generating an address
generateXAddress({entropy: random()}),
generateXAddress({ entropy: random() }),
// THEN we get the expected return value
responses.generateXAddress
)
})
);
});
it('generateAddress invalid entropy', () => {
it("generateAddress invalid entropy", function () {
assert.throws(() => {
// GIVEN entropy of 1 byte
function random() {
return new Array(1).fill(0)
return new Array(1).fill(0);
}
// WHEN generating an address
generateXAddress({entropy: random()})
generateXAddress({ entropy: random() });
// THEN an UnexpectedError is thrown
// because 16 bytes of entropy are required
}, UnexpectedError)
})
}, UnexpectedError);
});
it('generateAddress with no options object', () => {
it("generateAddress with no options object", function () {
// GIVEN no options
// WHEN generating an address
const account = generateXAddress()
const account = generateXAddress();
// THEN we get an object with an xAddress starting with 'x' and a secret starting with 's'
assert(account.xAddress.startsWith('X'), 'Address must start with `X`')
assert(account.secret.startsWith('s'), 'Secret must start with `s`')
})
assert(account.xAddress.startsWith("X"), "Address must start with `X`");
assert(account.secret.startsWith("s"), "Secret must start with `s`");
});
it('generateAddress with empty options object', () => {
it("generateAddress with empty options object", function () {
// GIVEN an empty options object
const options = {}
const options = {};
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get an object with an xAddress starting with 'x' and a secret starting with 's'
assert(account.xAddress.startsWith('X'), 'Address must start with `X`')
assert(account.secret.startsWith('s'), 'Secret must start with `s`')
})
assert(account.xAddress.startsWith("X"), "Address must start with `X`");
assert(account.secret.startsWith("s"), "Secret must start with `s`");
});
it('generateAddress with algorithm `ecdsa-secp256k1`', () => {
it("generateAddress with algorithm `ecdsa-secp256k1`", function () {
// GIVEN we want to use 'ecdsa-secp256k1'
const options: GenerateAddressOptions = {algorithm: ECDSA.secp256k1, includeClassicAddress: true}
const options: GenerateAddressOptions = {
algorithm: ECDSA.secp256k1,
includeClassicAddress: true,
};
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get an object with an address starting with 'r' and a secret starting with 's' (not 'sEd')
assert(account.classicAddress.startsWith('r'), 'Address must start with `r`')
assert(
account.classicAddress?.startsWith("r"),
"Address must start with `r`"
);
assert.deepEqual(
account.secret.slice(0, 1),
's',
"s",
`Secret ${account.secret} must start with 's'`
)
);
assert.notStrictEqual(
account.secret.slice(0, 3),
'sEd',
"sEd",
`secp256k1 secret ${account.secret} must not start with 'sEd'`
)
})
);
});
it('generateAddress with algorithm `ed25519`', () => {
it("generateAddress with algorithm `ed25519`", function () {
// GIVEN we want to use 'ed25519'
const options: GenerateAddressOptions = {algorithm: ECDSA.ed25519, includeClassicAddress: true}
const options: GenerateAddressOptions = {
algorithm: ECDSA.ed25519,
includeClassicAddress: true,
};
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get an object with an address starting with 'r' and a secret starting with 'sEd'
assert(account.classicAddress.startsWith('r'), 'Address must start with `r`')
assert(
account.classicAddress?.startsWith("r"),
"Address must start with `r`"
);
assert.deepEqual(
account.secret.slice(0, 3),
'sEd',
"sEd",
`Ed25519 secret ${account.secret} must start with 'sEd'`
)
})
);
});
it('generateAddress with algorithm `ecdsa-secp256k1` and given entropy', () => {
// GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.secp256k1,
entropy: new Array(16).fill(0)
}
// WHEN generating an address
const account = generateXAddress(options)
// THEN we get the expected return value
assert.deepEqual(account, responses.generateXAddress)
})
it('generateAddress with algorithm `ed25519` and given entropy', () => {
// GIVEN we want to use 'ed25519' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.ed25519,
entropy: new Array(16).fill(0)
}
// WHEN generating an address
const account = generateXAddress(options)
// THEN we get the expected return value
assert.deepEqual(account, {
// generateAddress return value always includes xAddress to encourage X-address adoption
xAddress: 'X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB',
secret: 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE'
})
})
it('generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address', () => {
it("generateAddress with algorithm `ecdsa-secp256k1` and given entropy", function () {
// GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.secp256k1,
entropy: new Array(16).fill(0),
includeClassicAddress: true
}
};
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get the expected return value
assert.deepEqual(account, responses.generateAddress)
})
assert.deepEqual(account, responses.generateXAddress);
});
it('generateAddress with algorithm `ed25519` and given entropy; include classic address', () => {
it("generateAddress with algorithm `ed25519` and given entropy", function () {
// GIVEN we want to use 'ed25519' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.ed25519,
entropy: new Array(16).fill(0),
includeClassicAddress: true
}
};
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get the expected return value
assert.deepEqual(account, {
// generateAddress return value always includes xAddress to encourage X-address adoption
xAddress: 'X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB',
xAddress: "X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB",
secret: "sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE",
});
});
secret: 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE',
classicAddress: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7',
address: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7'
})
})
it('generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address; for test network use', () => {
it("generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address", function () {
// GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.secp256k1,
entropy: new Array(16).fill(0),
includeClassicAddress: true,
test: true
}
};
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get the expected return value
const response = Object.assign({}, responses.generateAddress, {
// generateAddress return value always includes xAddress to encourage X-address adoption
xAddress: 'TVG3TcCD58BD6MZqsNuTihdrhZwR8SzvYS8U87zvHsAcNw4'
})
assert.deepEqual(account, response)
})
assert.deepEqual(account, responses.generateAddress);
});
it('generateAddress with algorithm `ed25519` and given entropy; include classic address; for test network use', () => {
it("generateAddress with algorithm `ed25519` and given entropy; include classic address", function () {
// GIVEN we want to use 'ed25519' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.ed25519,
entropy: new Array(16).fill(0),
includeClassicAddress: true,
test: true
}
};
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get the expected return value
assert.deepEqual(account, {
// generateAddress return value always includes xAddress to encourage X-address adoption
xAddress: 'T7t4HeTMF5tT68agwuVbJwu23ssMPeh8dDtGysZoQiij1oo',
secret: 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE',
classicAddress: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7',
address: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7'
})
})
xAddress: "X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB",
it('generateAddress for test network use', () => {
secret: "sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE",
classicAddress: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7",
address: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7",
});
});
it("generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address; for test network use", function () {
// GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.secp256k1,
entropy: new Array(16).fill(0),
includeClassicAddress: true,
test: true,
};
// WHEN generating an address
const account = generateXAddress(options);
// THEN we get the expected return value
const response = {
...responses.generateAddress, // generateAddress return value always includes xAddress to encourage X-address adoption
xAddress: "TVG3TcCD58BD6MZqsNuTihdrhZwR8SzvYS8U87zvHsAcNw4",
};
assert.deepEqual(account, response);
});
it("generateAddress with algorithm `ed25519` and given entropy; include classic address; for test network use", function () {
// GIVEN we want to use 'ed25519' with entropy of zero
const options: GenerateAddressOptions = {
algorithm: ECDSA.ed25519,
entropy: new Array(16).fill(0),
includeClassicAddress: true,
test: true,
};
// WHEN generating an address
const account = generateXAddress(options);
// THEN we get the expected return value
assert.deepEqual(account, {
// generateAddress return value always includes xAddress to encourage X-address adoption
xAddress: "T7t4HeTMF5tT68agwuVbJwu23ssMPeh8dDtGysZoQiij1oo",
secret: "sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE",
classicAddress: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7",
address: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7",
});
});
it("generateAddress for test network use", function () {
// GIVEN we want an address for test network use
const options: GenerateAddressOptions = {test: true}
const options: GenerateAddressOptions = { test: true };
// WHEN generating an address
const account = generateXAddress(options)
const account = generateXAddress(options);
// THEN we get an object with xAddress starting with 'T' and a secret starting with 's'
// generateAddress return value always includes xAddress to encourage X-address adoption
assert.deepEqual(
account.xAddress.slice(0, 1),
'T',
'Test addresses start with T'
)
"T",
"Test addresses start with T"
);
assert.deepEqual(
account.secret.slice(0, 1),
's',
"s",
`Secret ${account.secret} must start with 's'`
)
})
})
);
});
});

View File

@@ -1,161 +1,163 @@
import assert from 'assert'
import fs from 'fs'
import assert from "assert";
import fs from "fs";
import {
computeStateTreeHash,
computeTransactionTreeHash,
computeAccountRootIndex,
computeStateTreeHash,
computeTransactionTreeHash,
computeAccountRootIndex,
computeTrustlineHash,
computeOfferIndex,
computeSignerListIndex,
computeEscrowHash,
computePaymentChannelHash
} from '../../src/utils/hashes'
computePaymentChannelHash,
} from "../../src/utils/hashes";
/**
* Expects a corresponding ledger dump in $repo/test/fixtures/rippled folder
* Expects a corresponding ledger dump in $repo/test/fixtures/rippled folder.
*
* @param ledgerIndex
*/
function createLedgerTest(ledgerIndex: number) {
describe(String(ledgerIndex), function () {
var path =
__dirname + '/../fixtures/rippled/ledgerFull' + ledgerIndex + '.json'
const path = `${__dirname}/../fixtures/rippled/ledgerFull${ledgerIndex}.json`;
var ledgerRaw = fs.readFileSync(path, {encoding: 'utf8'})
var ledgerJSON = JSON.parse(ledgerRaw)
const ledgerRaw = fs.readFileSync(path, { encoding: "utf8" });
const ledgerJSON = JSON.parse(ledgerRaw);
var hasAccounts =
const hasAccounts =
Array.isArray(ledgerJSON.accountState) &&
ledgerJSON.accountState.length > 0
ledgerJSON.accountState.length > 0;
if (hasAccounts) {
it('has account_hash of ' + ledgerJSON.account_hash, function () {
it(`has account_hash of ${ledgerJSON.account_hash}`, function () {
assert.equal(
ledgerJSON.account_hash,
computeStateTreeHash(ledgerJSON.accountState)
)
})
);
});
}
it('has transaction_hash of ' + ledgerJSON.transaction_hash, function () {
it(`has transaction_hash of ${ledgerJSON.transaction_hash}`, function () {
assert.equal(
ledgerJSON.transaction_hash,
computeTransactionTreeHash(ledgerJSON.transactions)
)
})
})
);
});
});
}
describe('Ledger', function () {
describe("Ledger", function () {
// This is the first recorded ledger with a non empty transaction set
createLedgerTest(38129)
createLedgerTest(38129);
// Because, why not.
createLedgerTest(40000)
createLedgerTest(40000);
// 1311 AffectedNodes, no accounts
createLedgerTest(7501326)
createLedgerTest(7501326);
describe('calcAccountRootEntryHash', function () {
it('will calculate the AccountRoot entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', function () {
var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
var expectedEntryHash =
'2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8'
var actualEntryHash = computeAccountRootIndex(account)
describe("calcAccountRootEntryHash", function () {
it("will calculate the AccountRoot entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", function () {
const account = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
const expectedEntryHash =
"2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8";
const actualEntryHash = computeAccountRootIndex(account);
assert.equal(actualEntryHash, expectedEntryHash)
})
})
assert.equal(actualEntryHash, expectedEntryHash);
});
});
describe('calcRippleStateEntryHash', function () {
it('will calculate the RippleState entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh and rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY in USD', function () {
var account1 = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
var account2 = 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY'
var currency = 'USD'
describe("calcRippleStateEntryHash", function () {
it("will calculate the RippleState entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh and rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY in USD", function () {
const account1 = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
const account2 = "rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY";
const currency = "USD";
var expectedEntryHash =
'C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C'
var actualEntryHash1 = computeTrustlineHash(
const expectedEntryHash =
"C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C";
const actualEntryHash1 = computeTrustlineHash(
account1,
account2,
currency
)
var actualEntryHash2 = computeTrustlineHash(
);
const actualEntryHash2 = computeTrustlineHash(
account2,
account1,
currency
)
);
assert.equal(actualEntryHash1, expectedEntryHash)
assert.equal(actualEntryHash2, expectedEntryHash)
})
assert.equal(actualEntryHash1, expectedEntryHash);
assert.equal(actualEntryHash2, expectedEntryHash);
});
it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function () {
var account1 = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV'
var account2 = 'rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj'
var currency = 'UAM'
it("will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM", function () {
const account1 = "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV";
const account2 = "rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj";
const currency = "UAM";
var expectedEntryHash =
'AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E'
var actualEntryHash1 = computeTrustlineHash(
const expectedEntryHash =
"AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E";
const actualEntryHash1 = computeTrustlineHash(
account1,
account2,
currency
)
var actualEntryHash2 = computeTrustlineHash(
);
const actualEntryHash2 = computeTrustlineHash(
account2,
account1,
currency
)
);
assert.equal(actualEntryHash1, expectedEntryHash)
assert.equal(actualEntryHash2, expectedEntryHash)
})
})
assert.equal(actualEntryHash1, expectedEntryHash);
assert.equal(actualEntryHash2, expectedEntryHash);
});
});
describe('calcOfferEntryHash', function () {
it('will calculate the Offer entry hash for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw, sequence 137', function () {
var account = 'r32UufnaCGL82HubijgJGDmdE5hac7ZvLw'
var sequence = 137
var expectedEntryHash =
'03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3'
var actualEntryHash = computeOfferIndex(account, sequence)
describe("calcOfferEntryHash", function () {
it("will calculate the Offer entry hash for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw, sequence 137", function () {
const account = "r32UufnaCGL82HubijgJGDmdE5hac7ZvLw";
const sequence = 137;
const expectedEntryHash =
"03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3";
const actualEntryHash = computeOfferIndex(account, sequence);
assert.equal(actualEntryHash, expectedEntryHash)
})
})
assert.equal(actualEntryHash, expectedEntryHash);
});
});
describe('computeSignerListIndex', function () {
it('will calculate the SignerList index for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw', function () {
var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
var expectedEntryHash =
'778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF'
var actualEntryHash = computeSignerListIndex(account)
assert.equal(actualEntryHash, expectedEntryHash)
})
})
describe("computeSignerListIndex", function () {
it("will calculate the SignerList index for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw", function () {
const account = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
const expectedEntryHash =
"778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF";
const actualEntryHash = computeSignerListIndex(account);
assert.equal(actualEntryHash, expectedEntryHash);
});
});
describe('calcEscrowEntryHash', function () {
it('will calculate the Escrow entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x, sequence 84', function () {
var account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x'
var sequence = 84
var expectedEntryHash =
'61E8E8ED53FA2CEBE192B23897071E9A75217BF5A410E9CB5B45AAB7AECA567A'
var actualEntryHash = computeEscrowHash(account, sequence)
describe("calcEscrowEntryHash", function () {
it("will calculate the Escrow entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x, sequence 84", function () {
const account = "rDx69ebzbowuqztksVDmZXjizTd12BVr4x";
const sequence = 84;
const expectedEntryHash =
"61E8E8ED53FA2CEBE192B23897071E9A75217BF5A410E9CB5B45AAB7AECA567A";
const actualEntryHash = computeEscrowHash(account, sequence);
assert.equal(actualEntryHash, expectedEntryHash)
})
})
assert.equal(actualEntryHash, expectedEntryHash);
});
});
describe('calcPaymentChannelEntryHash', function () {
it('will calculate the PaymentChannel entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x and rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso, sequence 82', function () {
var account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x'
var dstAccount = 'rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso'
var sequence = 82
var expectedEntryHash =
'E35708503B3C3143FB522D749AAFCC296E8060F0FB371A9A56FAE0B1ED127366'
var actualEntryHash = computePaymentChannelHash(
describe("calcPaymentChannelEntryHash", function () {
it("will calculate the PaymentChannel entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x and rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso, sequence 82", function () {
const account = "rDx69ebzbowuqztksVDmZXjizTd12BVr4x";
const dstAccount = "rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso";
const sequence = 82;
const expectedEntryHash =
"E35708503B3C3143FB522D749AAFCC296E8060F0FB371A9A56FAE0B1ED127366";
const actualEntryHash = computePaymentChannelHash(
account,
dstAccount,
sequence
)
);
assert.equal(actualEntryHash, expectedEntryHash)
})
})
})
assert.equal(actualEntryHash, expectedEntryHash);
});
});
});

View File

@@ -1,26 +1,21 @@
import {assertResultMatch} from '../testUtils'
import responses from '../fixtures/responses'
import signPaymentChannelClaim from '../../src/utils/signPaymentChannelClaim'
import signPaymentChannelClaim from "../../src/utils/signPaymentChannelClaim";
import responses from "../fixtures/responses";
import { assertResultMatch } from "../testUtils";
describe("signPaymentChannelClaim", function () {
it("basic signature matches", function () {
const channel =
"3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037";
const amount = ".00001";
const privateKey =
"ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A";
const result = signPaymentChannelClaim(channel, amount, privateKey);
describe('signPaymentChannelClaim', function () {
it('basic signature matches', () => {
const channel = "3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037"
const amount = ".00001"
const privateKey = 'ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A'
const result = signPaymentChannelClaim(
channel,
amount,
privateKey
)
assertResultMatch(
result,
responses.signPaymentChannelClaim,
'signPaymentChannelClaim'
)
})
})
"signPaymentChannelClaim"
);
});
});

View File

@@ -1,30 +1,30 @@
import {verifyPaymentChannelClaim} from '../../src'
import requests from '../fixtures/requests'
import responses from '../fixtures/responses'
import {assertResultMatch} from '../testUtils'
import { verifyPaymentChannelClaim } from "../../src";
import requests from "../fixtures/requests";
import responses from "../fixtures/responses";
import { assertResultMatch } from "../testUtils";
describe('Verify Payment Channel Claim', function () {
it('basic verification works', () => {
describe("Verify Payment Channel Claim", function () {
it("basic verification works", function () {
const publicKey =
'02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8'
"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8";
const result = verifyPaymentChannelClaim(
requests.signPaymentChannelClaim.channel,
requests.signPaymentChannelClaim.amount,
responses.signPaymentChannelClaim,
publicKey
)
assertResultMatch(result, true, 'verifyPaymentChannelClaim')
})
);
assertResultMatch(result, true, "verifyPaymentChannelClaim");
});
it('invalid payment channel claim fails', () => {
it("invalid payment channel claim fails", function () {
const publicKey =
'03A6523FE4281DA48A6FD77FAF3CB77F5C7001ABA0B32BCEDE0369AC009758D7D9'
"03A6523FE4281DA48A6FD77FAF3CB77F5C7001ABA0B32BCEDE0369AC009758D7D9";
const result = verifyPaymentChannelClaim(
requests.signPaymentChannelClaim.channel,
requests.signPaymentChannelClaim.amount,
responses.signPaymentChannelClaim,
publicKey
)
assertResultMatch(result, false, 'verifyPaymentChannelClaim')
})
})
);
assertResultMatch(result, false, "verifyPaymentChannelClaim");
});
});

View File

@@ -1,108 +1,109 @@
import assert from 'assert-diff'
import BigNumber from 'bignumber.js'
import {xrpToDrops} from '../../src/utils'
import assert from "assert-diff";
import BigNumber from "bignumber.js";
describe('XRP To Drops', function () {
it('works with a typical amount', () => {
const drops = xrpToDrops('2')
assert.strictEqual(drops, '2000000', '2 XRP equals 2 million drops')
})
import { xrpToDrops } from "../../src/utils";
it('works with fractions', () => {
let drops = xrpToDrops('3.456789')
assert.strictEqual(drops, '3456789', '3.456789 XRP equals 3,456,789 drops')
drops = xrpToDrops('3.400000')
assert.strictEqual(drops, '3400000', '3.400000 XRP equals 3,400,000 drops')
drops = xrpToDrops('0.000001')
assert.strictEqual(drops, '1', '0.000001 XRP equals 1 drop')
drops = xrpToDrops('0.0000010')
assert.strictEqual(drops, '1', '0.0000010 XRP equals 1 drop')
})
describe("XRP To Drops", function () {
it("works with a typical amount", function () {
const drops = xrpToDrops("2");
assert.strictEqual(drops, "2000000", "2 XRP equals 2 million drops");
});
it('works with zero', () => {
let drops = xrpToDrops('0')
assert.strictEqual(drops, '0', '0 XRP equals 0 drops')
drops = xrpToDrops('-0') // negative zero is equivalent to zero
assert.strictEqual(drops, '0', '-0 XRP equals 0 drops')
drops = xrpToDrops('0.000000')
assert.strictEqual(drops, '0', '0.000000 XRP equals 0 drops')
drops = xrpToDrops('0.0000000')
assert.strictEqual(drops, '0', '0.0000000 XRP equals 0 drops')
})
it("works with fractions", function () {
let drops = xrpToDrops("3.456789");
assert.strictEqual(drops, "3456789", "3.456789 XRP equals 3,456,789 drops");
drops = xrpToDrops("3.400000");
assert.strictEqual(drops, "3400000", "3.400000 XRP equals 3,400,000 drops");
drops = xrpToDrops("0.000001");
assert.strictEqual(drops, "1", "0.000001 XRP equals 1 drop");
drops = xrpToDrops("0.0000010");
assert.strictEqual(drops, "1", "0.0000010 XRP equals 1 drop");
});
it('works with a negative value', () => {
const drops = xrpToDrops('-2')
assert.strictEqual(drops, '-2000000', '-2 XRP equals -2 million drops')
})
it("works with zero", function () {
let drops = xrpToDrops("0");
assert.strictEqual(drops, "0", "0 XRP equals 0 drops");
drops = xrpToDrops("-0"); // negative zero is equivalent to zero
assert.strictEqual(drops, "0", "-0 XRP equals 0 drops");
drops = xrpToDrops("0.000000");
assert.strictEqual(drops, "0", "0.000000 XRP equals 0 drops");
drops = xrpToDrops("0.0000000");
assert.strictEqual(drops, "0", "0.0000000 XRP equals 0 drops");
});
it('works with a value ending with a decimal point', () => {
let drops = xrpToDrops('2.')
assert.strictEqual(drops, '2000000', '2. XRP equals 2000000 drops')
drops = xrpToDrops('-2.')
assert.strictEqual(drops, '-2000000', '-2. XRP equals -2000000 drops')
})
it("works with a negative value", function () {
const drops = xrpToDrops("-2");
assert.strictEqual(drops, "-2000000", "-2 XRP equals -2 million drops");
});
it('works with BigNumber objects', () => {
let drops = xrpToDrops(new BigNumber(2))
it("works with a value ending with a decimal point", function () {
let drops = xrpToDrops("2.");
assert.strictEqual(drops, "2000000", "2. XRP equals 2000000 drops");
drops = xrpToDrops("-2.");
assert.strictEqual(drops, "-2000000", "-2. XRP equals -2000000 drops");
});
it("works with BigNumber objects", function () {
let drops = xrpToDrops(new BigNumber(2));
assert.strictEqual(
drops,
'2000000',
'(BigNumber) 2 XRP equals 2 million drops'
)
drops = xrpToDrops(new BigNumber(-2))
"2000000",
"(BigNumber) 2 XRP equals 2 million drops"
);
drops = xrpToDrops(new BigNumber(-2));
assert.strictEqual(
drops,
'-2000000',
'(BigNumber) -2 XRP equals -2 million drops'
)
})
"-2000000",
"(BigNumber) -2 XRP equals -2 million drops"
);
});
it('works with a number', () => {
it("works with a number", function () {
// This is not recommended. Use strings or BigNumber objects to avoid precision errors.
let drops = xrpToDrops(2)
let drops = xrpToDrops(2);
assert.strictEqual(
drops,
'2000000',
'(number) 2 XRP equals 2 million drops'
)
drops = xrpToDrops(-2)
"2000000",
"(number) 2 XRP equals 2 million drops"
);
drops = xrpToDrops(-2);
assert.strictEqual(
drops,
'-2000000',
'(number) -2 XRP equals -2 million drops'
)
})
"-2000000",
"(number) -2 XRP equals -2 million drops"
);
});
it('throws with an amount with too many decimal places', () => {
it("throws with an amount with too many decimal places", function () {
assert.throws(() => {
xrpToDrops('1.1234567')
}, /has too many decimal places/)
xrpToDrops("1.1234567");
}, /has too many decimal places/);
assert.throws(() => {
xrpToDrops('0.0000001')
}, /has too many decimal places/)
})
xrpToDrops("0.0000001");
}, /has too many decimal places/);
});
it('throws with an invalid value', () => {
it("throws with an invalid value", function () {
assert.throws(() => {
xrpToDrops('FOO')
}, /invalid value/)
xrpToDrops("FOO");
}, /invalid value/);
assert.throws(() => {
xrpToDrops('1e-7')
}, /invalid value/)
xrpToDrops("1e-7");
}, /invalid value/);
assert.throws(() => {
xrpToDrops('2,0')
}, /invalid value/)
xrpToDrops("2,0");
}, /invalid value/);
assert.throws(() => {
xrpToDrops('.')
}, /xrpToDrops: invalid value '\.', should be a BigNumber or string-encoded number\./)
})
xrpToDrops(".");
}, /xrpToDrops: invalid value '\.', should be a BigNumber or string-encoded number\./);
});
it('throws with an amount more than one decimal point', () => {
it("throws with an amount more than one decimal point", function () {
assert.throws(() => {
xrpToDrops('1.0.0')
}, /xrpToDrops: invalid value '1\.0\.0'/)
xrpToDrops("1.0.0");
}, /xrpToDrops: invalid value '1\.0\.0'/);
assert.throws(() => {
xrpToDrops('...')
}, /xrpToDrops: invalid value '\.\.\.'/)
})
})
xrpToDrops("...");
}, /xrpToDrops: invalid value '\.\.\.'/);
});
});

View File

@@ -1,17 +1,18 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import ECDSA from '../../src/common/ecdsa'
import Wallet from '../../src/Wallet'
import assert from "assert-diff";
const entropy: number[] = new Array(16).fill(0)
const publicKey: string =
'0390A196799EE412284A5D80BF78C3E84CBB80E1437A0AECD9ADF94D7FEAAFA284'
const privateKey: string =
'002512BBDFDBB77510883B7DCCBEF270B86DEAC8B64AC762873D75A1BEE6298665'
const publicKeyED25519: string =
'ED1A7C082846CFF58FF9A892BA4BA2593151CCF1DBA59F37714CC9ED39824AF85F'
const privateKeyED25519: string =
'ED0B6CBAC838DFE7F47EA1BD0DF00EC282FDF45510C92161072CCFB84035390C4D'
import ECDSA from "../../src/common/ecdsa";
import Wallet from "../../src/Wallet";
import { TestSuite } from "../testUtils";
const entropy: number[] = new Array(16).fill(0);
const publicKey =
"0390A196799EE412284A5D80BF78C3E84CBB80E1437A0AECD9ADF94D7FEAAFA284";
const privateKey =
"002512BBDFDBB77510883B7DCCBEF270B86DEAC8B64AC762873D75A1BEE6298665";
const publicKeyED25519 =
"ED1A7C082846CFF58FF9A892BA4BA2593151CCF1DBA59F37714CC9ED39824AF85F";
const privateKeyED25519 =
"ED0B6CBAC838DFE7F47EA1BD0DF00EC282FDF45510C92161072CCFB84035390C4D";
/**
* Every test suite exports their tests in the default object.
@@ -19,36 +20,36 @@ const privateKeyED25519: string =
* - Check out "test/api/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'Wallet.fromEntropy with entropy only': async (api) => {
"Wallet.fromEntropy with entropy only": async (api) => {
// WHEN deriving a wallet from an entropy
const wallet = Wallet.fromEntropy(entropy)
const wallet = Wallet.fromEntropy(entropy);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKeyED25519)
assert.equal(wallet.privateKey, privateKeyED25519)
assert.equal(wallet.publicKey, publicKeyED25519);
assert.equal(wallet.privateKey, privateKeyED25519);
},
'Wallet.fromEntropy with algorithm ecdsa-secp256k1': async (api) => {
"Wallet.fromEntropy with algorithm ecdsa-secp256k1": async (api) => {
// GIVEN an entropy using ecdsa-secp256k1
const algorithm = ECDSA.secp256k1
const algorithm = ECDSA.secp256k1;
// WHEN deriving a wallet from an entropy
const wallet = Wallet.fromEntropy(entropy, algorithm)
const wallet = Wallet.fromEntropy(entropy, algorithm);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKey)
assert.equal(wallet.privateKey, privateKey)
assert.equal(wallet.publicKey, publicKey);
assert.equal(wallet.privateKey, privateKey);
},
'Wallet.fromEntropy with algorithm ed25519': async (api) => {
"Wallet.fromEntropy with algorithm ed25519": async (api) => {
// GIVEN an entropy using ed25519
const algorithm = ECDSA.ed25519
const algorithm = ECDSA.ed25519;
// WHEN deriving a wallet from an entropy
const wallet = Wallet.fromEntropy(entropy, algorithm)
const wallet = Wallet.fromEntropy(entropy, algorithm);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKeyED25519)
assert.equal(wallet.privateKey, privateKeyED25519)
assert.equal(wallet.publicKey, publicKeyED25519);
assert.equal(wallet.privateKey, privateKeyED25519);
},
}
};

View File

@@ -1,13 +1,14 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import Wallet from '../../src/Wallet'
import assert from "assert-diff";
import Wallet from "../../src/Wallet";
import { TestSuite } from "../testUtils";
const mnemonic =
'try milk link drift aware pass obtain again music stick pluck fold'
"try milk link drift aware pass obtain again music stick pluck fold";
const publicKey =
'0257B550BA2FDCCF0ADDA3DEB2A5411700F3ADFDCC7C68E1DCD1E2B63E6B0C63E6'
"0257B550BA2FDCCF0ADDA3DEB2A5411700F3ADFDCC7C68E1DCD1E2B63E6B0C63E6";
const privateKey =
'008F942B6E229C0E9CEE47E7A94253DABB6A9855F4BA2D8A741FA31851A1D423C3'
"008F942B6E229C0E9CEE47E7A94253DABB6A9855F4BA2D8A741FA31851A1D423C3";
/**
* Every test suite exports their tests in the default object.
@@ -15,25 +16,25 @@ const privateKey =
* - Check out "test/api/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'Wallet.fromMnemonic using default derivation path': async (api) => {
"Wallet.fromMnemonic using default derivation path": async (api) => {
// GIVEN no derivation path
// WHEN deriving a wallet from a mnemonic without a derivation path
const wallet = Wallet.fromMnemonic(mnemonic)
const wallet = Wallet.fromMnemonic(mnemonic);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKey)
assert.equal(wallet.privateKey, privateKey)
assert.equal(wallet.publicKey, publicKey);
assert.equal(wallet.privateKey, privateKey);
},
'Wallet.fromMnemonic using an input derivation path': async (api) => {
"Wallet.fromMnemonic using an input derivation path": async (api) => {
// GIVEN a derivation path
const derivationPath = "m/44'/144'/0'/0/0"
const derivationPath = "m/44'/144'/0'/0/0";
// WHEN deriving a wallet from a mnemonic without a derivation path
const wallet = Wallet.fromMnemonic(mnemonic, derivationPath)
const wallet = Wallet.fromMnemonic(mnemonic, derivationPath);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKey)
assert.equal(wallet.privateKey, privateKey)
assert.equal(wallet.publicKey, publicKey);
assert.equal(wallet.privateKey, privateKey);
},
}
};

View File

@@ -1,13 +1,14 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import ECDSA from '../../src/common/ecdsa'
import Wallet from '../../src/Wallet'
import assert from "assert-diff";
const seed = 'ssL9dv2W5RK8L3tuzQxYY6EaZhSxW'
import ECDSA from "../../src/common/ecdsa";
import Wallet from "../../src/Wallet";
import { TestSuite } from "../testUtils";
const seed = "ssL9dv2W5RK8L3tuzQxYY6EaZhSxW";
const publicKey =
'030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D'
"030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D";
const privateKey =
'00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F'
"00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F";
/**
* Every test suite exports their tests in the default object.
@@ -15,36 +16,36 @@ const privateKey =
* - Check out "test/api/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'Wallet.fromSeed with empty options object': async (api) => {
"Wallet.fromSeed with empty options object": async (api) => {
// WHEN deriving a wallet from a seed
const wallet = Wallet.fromSeed(seed)
const wallet = Wallet.fromSeed(seed);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKey)
assert.equal(wallet.privateKey, privateKey)
assert.equal(wallet.publicKey, publicKey);
assert.equal(wallet.privateKey, privateKey);
},
'Wallet.fromSeed with algorithm ecdsa-secp256k1': async (api) => {
"Wallet.fromSeed with algorithm ecdsa-secp256k1": async (api) => {
// GIVEN we want to use ecdsa-secp256k1
const algorithm = ECDSA.secp256k1
const algorithm = ECDSA.secp256k1;
// WHEN deriving a wallet from a seed
const wallet = Wallet.fromSeed(seed, algorithm)
const wallet = Wallet.fromSeed(seed, algorithm);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKey)
assert.equal(wallet.privateKey, privateKey)
assert.equal(wallet.publicKey, publicKey);
assert.equal(wallet.privateKey, privateKey);
},
'Wallet.fromSeed with algorithm ed25519': async (api) => {
"Wallet.fromSeed with algorithm ed25519": async (api) => {
// GIVEN we want to use ed25519
const algorithm = ECDSA.ed25519
const algorithm = ECDSA.ed25519;
// WHEN deriving a wallet from a seed
const wallet = Wallet.fromSeed(seed, algorithm)
const wallet = Wallet.fromSeed(seed, algorithm);
// THEN we get a wallet with a keypair (publicKey/privateKey)
assert.equal(wallet.publicKey, publicKey)
assert.equal(wallet.privateKey, privateKey)
assert.equal(wallet.publicKey, publicKey);
assert.equal(wallet.privateKey, privateKey);
},
}
};

View File

@@ -1,12 +1,13 @@
import {TestSuite} from '../testUtils'
import Wallet from '../../src/Wallet'
import * as schemaValidator from 'xrpl-local/common/schema-validator'
import * as schemaValidator from "xrpl-local/common/schema-validator";
import Wallet from "../../src/Wallet";
import { TestSuite } from "../testUtils";
const publicKey =
'030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D'
"030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D";
const privateKey =
'00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F'
const address = 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc'
"00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F";
const address = "rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc";
/**
* Every test suite exports their tests in the default object.
@@ -14,24 +15,24 @@ const address = 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc'
* - Check out "test/api/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'sign transaction offline with txJSON': async (api) => {
"sign transaction offline with txJSON": async (api) => {
// GIVEN a transaction
const txJSON = {
TransactionType: 'Payment',
TransactionType: "Payment",
Account: address,
Destination: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r',
Amount: '20000000',
Destination: "rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r",
Amount: "20000000",
Sequence: 1,
Fee: '12',
SigningPubKey: publicKey
}
const wallet = new Wallet(publicKey, privateKey)
Fee: "12",
SigningPubKey: publicKey,
};
const wallet = new Wallet(publicKey, privateKey);
// WHEN signing a transaction offline
const signedTx: {signedTransaction: string; id: string} =
wallet.signTransaction(txJSON)
const signedTx: { signedTransaction: string; id: string } =
wallet.signTransaction(txJSON);
// THEN we get a signedTransaction
schemaValidator.schemaValidate('sign', signedTx)
schemaValidator.schemaValidate("sign", signedTx);
},
}
};

View File

@@ -1,16 +1,18 @@
import assert from 'assert-diff'
import {TestSuite} from '../testUtils'
import Wallet from 'xrpl-local/Wallet'
import assert from "assert-diff";
import Wallet from "xrpl-local/Wallet";
import { TestSuite } from "../testUtils";
const publicKey =
'030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D'
"030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D";
const privateKey =
'00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F'
"00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F";
const prepared = {
signedTransaction:
'1200002400000001614000000001312D0068400000000000000C7321030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D74473045022100CAF99A63B241F5F62B456C68A593D2835397101533BB5D0C4DC17362AC22046F022016A2CA2CF56E777B10E43B56541A4C2FB553E7E298CDD39F7A8A844DA491E51D81142AF1861DEC1316AEEC995C94FF9E2165B1B784608314FDB08D07AAA0EB711793A3027304D688E10C3648',
id: '30D9ECA2A7FB568C5A8607E5850D9567572A9E7C6094C26BEFD4DC4C2CF2657A'
}
"1200002400000001614000000001312D0068400000000000000C7321030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D74473045022100CAF99A63B241F5F62B456C68A593D2835397101533BB5D0C4DC17362AC22046F022016A2CA2CF56E777B10E43B56541A4C2FB553E7E298CDD39F7A8A844DA491E51D81142AF1861DEC1316AEEC995C94FF9E2165B1B784608314FDB08D07AAA0EB711793A3027304D688E10C3648",
id: "30D9ECA2A7FB568C5A8607E5850D9567572A9E7C6094C26BEFD4DC4C2CF2657A",
};
/**
* Every test suite exports their tests in the default object.
@@ -18,29 +20,37 @@ const prepared = {
* - Check out "test/api/index.ts" for more information about the test runner.
*/
export default <TestSuite>{
'verify transaction offline when a signed transaction is valid': async (api) => {
"verify transaction offline when a signed transaction is valid": async (
api
) => {
// GIVEN a transaction that has been signed by the same wallet
const wallet = new Wallet(publicKey, privateKey)
const wallet = new Wallet(publicKey, privateKey);
// WHEN verifying a signed transaction
const isVerified: boolean = wallet.verifyTransaction(prepared.signedTransaction)
const isVerified: boolean = wallet.verifyTransaction(
prepared.signedTransaction
);
// THEN we get a valid response
assert.equal(isVerified, true)
assert.equal(isVerified, true);
},
"verify transaction offline when signed transaction isn't valid": async (api) => {
"verify transaction offline when signed transaction isn't valid": async (
api
) => {
// GIVEN a transaction that has been signed by a different wallet
const diffPublicKey =
'02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8'
"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8";
const diffPrivateKey =
'00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A'
const wallet = new Wallet(diffPublicKey, diffPrivateKey)
"00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A";
const wallet = new Wallet(diffPublicKey, diffPrivateKey);
// WHEN verifying a signed transaction
const isVerified: boolean = wallet.verifyTransaction(prepared.signedTransaction)
const isVerified: boolean = wallet.verifyTransaction(
prepared.signedTransaction
);
// THEN we get an invalid response
assert.equal(isVerified, false)
assert.equal(isVerified, false);
},
}
};

View File

@@ -1,35 +1,36 @@
import assert from 'assert-diff'
import assert from "assert-diff";
import setupClient from './setupClient'
import {getFaucetUrl, FaucetNetwork} from '../src/wallet/wallet-generation'
import { getFaucetUrl, FaucetNetwork } from "../src/wallet/wallet-generation";
describe('Get Faucet URL', function () {
beforeEach(setupClient.setup)
afterEach(setupClient.teardown)
import setupClient from "./setupClient";
it('returns the Devnet URL', function () {
const expectedFaucet = FaucetNetwork.Devnet
this.client.connection._url = FaucetNetwork.Devnet
describe("Get Faucet URL", function () {
beforeEach(setupClient.setup);
afterEach(setupClient.teardown);
assert.strictEqual(getFaucetUrl(this.client), expectedFaucet)
})
it("returns the Devnet URL", function () {
const expectedFaucet = FaucetNetwork.Devnet;
this.client.connection._url = FaucetNetwork.Devnet;
it('returns the Testnet URL', function () {
const expectedFaucet = FaucetNetwork.Testnet
this.client.connection._url = FaucetNetwork.Testnet
assert.strictEqual(getFaucetUrl(this.client), expectedFaucet);
});
assert.strictEqual(getFaucetUrl(this.client), expectedFaucet)
})
it("returns the Testnet URL", function () {
const expectedFaucet = FaucetNetwork.Testnet;
this.client.connection._url = FaucetNetwork.Testnet;
it('returns the Testnet URL with the XRPL Labs server', function () {
const expectedFaucet = FaucetNetwork.Testnet
this.client.connection._url = 'wss://testnet.xrpl-labs.com'
assert.strictEqual(getFaucetUrl(this.client), expectedFaucet);
});
assert.strictEqual(getFaucetUrl(this.client), expectedFaucet)
})
it("returns the Testnet URL with the XRPL Labs server", function () {
const expectedFaucet = FaucetNetwork.Testnet;
this.client.connection._url = "wss://testnet.xrpl-labs.com";
it('returns undefined if not a Testnet or Devnet server URL', function () {
assert.strictEqual(getFaucetUrl(this.client), expectedFaucet);
});
it("returns undefined if not a Testnet or Devnet server URL", function () {
// Info: setupClient.setup creates a connection to 'localhost'
assert.strictEqual(getFaucetUrl(this.client), undefined)
})
})
assert.strictEqual(getFaucetUrl(this.client), undefined);
});
});