itns-sidechain/test/wallet-importname-test.js
2023-01-16 23:49:05 +04:00

295 lines
9.3 KiB
JavaScript

'use strict';
const assert = require('bsert');
const Network = require('../lib/protocol/network');
const FullNode = require('../lib/node/fullnode');
const Address = require('../lib/primitives/address');
const rules = require('../lib/covenants/rules');
const WalletClient = require('../lib/client/wallet');
const {forValue} = require('./util/common');
const network = Network.get('regtest');
const ports = {
p2p: 14331,
node: 14332,
wallet: 14333
};
const node = new FullNode({
memory: true,
network: 'regtest',
plugins: [require('../lib/wallet/plugin')],
env: {
'HSD_WALLET_HTTP_PORT': ports.wallet.toString()
}
});
const wclient = new WalletClient({
port: ports.wallet
});
const {wdb} = node.require('walletdb');
const GNAME_SIZE = 10;
const name = rules.grindName(GNAME_SIZE, 1, network);
const nameHash = rules.hashName(name);
const wrongName = rules.grindName(GNAME_SIZE, 1, network);
const wrongNameHash = rules.hashName(wrongName);
let alice, bob, aliceReceive, bobReceive;
let charlie;
async function mineBlocks(n, addr) {
addr = addr ? addr : new Address().toString('regtest');
for (let i = 0; i < n; i++) {
const block = await node.miner.mineBlock(null, addr);
await node.chain.add(block);
}
}
describe('Wallet Import Name', function() {
before(async () => {
await node.open();
await wclient.open();
alice = await wdb.create();
bob = await wdb.create();
charlie = await wdb.create({id: 'charlie'});
aliceReceive = await alice.receiveAddress();
bobReceive = await bob.receiveAddress();
});
after(async () => {
await wclient.close();
await node.close();
});
it('should fund both wallets', async () => {
await mineBlocks(2, aliceReceive);
await mineBlocks(2, bobReceive);
// Wallet rescan is an effective way to ensure that
// wallet and chain are synced before proceeding.
await wdb.rescan(0);
const aliceBal = await alice.getBalance();
const bobBal = await bob.getBalance();
assert(aliceBal.confirmed === 2000 * 2 * 1e6);
assert(bobBal.confirmed === 2000 * 2 * 1e6);
});
it('should open name from Alice\'s wallet', async () => {
// Alice an Bob are not tracking this name
const ns1 = await alice.getNameStateByName(name);
assert(ns1 === null);
const ns2 = await bob.getNameStateByName(name);
assert(ns2 === null);
await alice.sendOpen(name, false);
await alice.sendOpen(wrongName, false);
await mineBlocks(network.names.treeInterval);
await wdb.rescan(0);
// Alice is now tracking, Bob is not
const ns3 = await alice.getNameStateByName(name);
assert(ns3);
const ns4 = await bob.getNameStateByName(name);
assert(ns4 === null);
});
it('should not re-import an existing name', async () => {
await assert.rejects(
alice.importName(name),
{message: 'Name already exists.'}
);
});
it('should bid on names from Alice\'s wallet', async () => {
// Sanity check: bids are allowed starting in the NEXT block
await assert.rejects(
alice.sendBid(name, 100001, 200001),
{message: `Name has not reached the bidding phase yet: ${name}.`}
);
await mineBlocks(1);
await wdb.rescan(0);
// Send 1 bid, confirm
await alice.sendBid(name, 100001, 200001);
await mineBlocks(1);
// Send 2 bids in one block, confirm
await alice.sendBid(name, 100002, 200002);
await alice.sendBid(name, 100003, 200003);
await mineBlocks(1);
// Send 3 bids in one block, confirm
await alice.sendBid(name, 100004, 200004);
await alice.sendBid(name, 100005, 200005);
await alice.sendBid(name, 100006, 200006);
await mineBlocks(1);
// One block with some bids for another name
await alice.sendBid(wrongName, 100007, 200007);
await alice.sendBid(wrongName, 100008, 200008);
await mineBlocks(1);
// Still in the bidding phase with one block left
const ns = await node.chain.db.getNameStateByName(name);
assert(ns.isBidding(node.chain.height + 1, network));
await wdb.rescan(0);
// Alice is tracking auction, Bob is not
const aliceBids = await alice.getBidsByName(name);
assert.strictEqual(aliceBids.length, 6);
for (const bid of aliceBids)
assert(bid.own);
const bobBids = await bob.getBidsByName(name);
assert.strictEqual(bobBids.length, 0);
});
it('should import name into Bob\'s wallet', async () => {
await bob.importName(name);
// Bob's wallet still has no name data for this name
const ns1 = await bob.getNameStateByName(name);
assert(ns1 === null);
// The WalletDB knows Alice & Bob are watching this name
const map1 = await wdb.getNameMap(nameHash);
assert(map1.wids.has(alice.wid));
assert(map1.wids.has(bob.wid));
// Only Alice is watching the other name
const map2 = await wdb.getNameMap(wrongNameHash);
assert(map1.wids.has(alice.wid));
assert(!map2.wids.has(bob.wid));
});
it('should not track bids for imported name before OPEN', async () => {
// Rescan covers bidding phase but does not include OPEN transaction
await wdb.rescan(6);
// Alice is tracking auction, Bob is not
const aliceBids = await alice.getBidsByName(name);
assert.strictEqual(aliceBids.length, 6);
for (const bid of aliceBids)
assert(bid.own);
const bobBids = await bob.getBidsByName(name);
assert.strictEqual(bobBids.length, 0);
});
it('should start tracking bids after seeing OPEN', async () => {
await wdb.rescan(0);
// After a sufficient rescan, Bob now has all auction data
const ns2 = await bob.getNameStateByName(name);
assert(ns2);
// ...even though he hasn't placed a bid yet
const bobBids = await bob.getBidsByName(name);
assert.strictEqual(bobBids.length, 6);
for (const bid of bobBids)
assert(!bid.own);
// Sanity check: only the "right" name was imported
const ns3 = await bob.getNameStateByName(wrongName);
assert(ns3 === null);
const ns4 = await alice.getNameStateByName(wrongName);
assert(ns4);
});
describe('rpc importname', function() {
it('should not have name data in Charlie\'s wallet', async () => {
const ns1 = await charlie.getNameStateByName(name);
assert(ns1 === null);
});
it('should import name with rescan', async () => {
await wclient.execute('selectwallet', ['charlie']);
await wclient.execute('importname', [name, 0]);
const ns1 = await charlie.getNameStateByName(name);
assert(ns1);
const charlieBids = await bob.getBidsByName(name);
assert.strictEqual(charlieBids.length, 6);
for (const bid of charlieBids)
assert(!bid.own);
});
it('should not re-import name', async () => {
await wclient.execute('selectwallet', ['charlie']);
await assert.rejects(
wclient.execute('importname', [name, 0]),
{message: 'Name already exists.'}
);
});
});
describe('import multiple / overlapping names', function() {
const name1 = rules.grindName(GNAME_SIZE, 1, network);
const name2 = rules.grindName(GNAME_SIZE, 1, network);
const name3 = rules.grindName(GNAME_SIZE, 1, network);
let startHeight;
it('should open and bid from Alice\'s wallet', async () => {
await alice.sendOpen(name1, false);
await alice.sendOpen(name2, false);
await alice.sendOpen(name3, false);
startHeight = node.chain.tip.height;
await mineBlocks(network.names.treeInterval + 1);
await forValue(wdb, 'height', node.chain.height);
await alice.sendBid(name1, 10000, 10000);
await alice.sendBid(name2, 20000, 20000);
await alice.sendBid(name3, 30000, 30000);
await mineBlocks(1);
});
it('should import names into Bob\'s wallet', async () => {
assert.strictEqual(await bob.getNameStateByName(name1), null);
assert.strictEqual(await bob.getNameStateByName(name2), null);
assert.strictEqual(await bob.getNameStateByName(name3), null);
assert.deepStrictEqual(await bob.getBidsByName(name1), []);
assert.deepStrictEqual(await bob.getBidsByName(name2), []);
assert.deepStrictEqual(await bob.getBidsByName(name3), []);
await bob.importName(name1);
await wdb.rescan(startHeight);
assert.ok(await bob.getNameStateByName(name1));
assert.strictEqual(await bob.getNameStateByName(name2), null);
assert.strictEqual(await bob.getNameStateByName(name3), null);
assert.ok(await bob.getBidsByName(name1));
assert.deepStrictEqual(await bob.getBidsByName(name2), []);
assert.deepStrictEqual(await bob.getBidsByName(name3), []);
await bob.importName(name2);
await wdb.rescan(startHeight);
assert.ok(await bob.getNameStateByName(name1));
assert.ok(await bob.getNameStateByName(name2));
assert.strictEqual(await bob.getNameStateByName(name3), null);
assert.ok(await bob.getBidsByName(name1));
assert.ok(await bob.getBidsByName(name2));
assert.deepStrictEqual(await bob.getBidsByName(name3), []);
await bob.importName(name3);
await wdb.rescan(startHeight);
assert.ok(await bob.getNameStateByName(name1));
assert.ok(await bob.getNameStateByName(name2));
assert.ok(await bob.getNameStateByName(name3));
assert.ok(await bob.getBidsByName(name1));
assert.ok(await bob.getBidsByName(name2));
assert.ok(await bob.getBidsByName(name3));
});
});
});