mirror of
https://github.com/alexgo-io/stacks-blockchain-api.git
synced 2026-01-12 16:53:19 +08:00
chore: fix flaky BNS tests #723
This commit is contained in:
@@ -55,6 +55,14 @@ export const testnetKeys: { secretKey: string; stacksAddress: string }[] = [
|
||||
secretKey: 'e75dcb66f84287eaf347955e94fa04337298dbd95aa0dbb985771104ef1913db01',
|
||||
stacksAddress: 'STRYYQQ9M8KAF4NS7WNZQYY59X93XEKR31JP64CP',
|
||||
},
|
||||
{
|
||||
secretKey: 'ce109fee08860bb16337c76647dcbc02df0c06b455dd69bcf30af74d4eedd19301',
|
||||
stacksAddress: 'STF9B75ADQAVXQHNEQ6KGHXTG7JP305J2GRWF3A2',
|
||||
},
|
||||
{
|
||||
secretKey: '08c14a1eada0dd42b667b40f59f7c8dedb12113613448dc04980aea20b268ddb01',
|
||||
stacksAddress: 'ST18MDW2PDTBSCR1ACXYRJP2JX70FWNM6YY2VX4SS',
|
||||
},
|
||||
];
|
||||
|
||||
export const testnetKeyMap: Record<
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
|
||||
|
||||
|
||||
import { PgDataStore, cycleMigrations, runMigrations } from '../datastore/postgres-store';
|
||||
import { PoolClient } from 'pg';
|
||||
import { ApiServer, startApiServer } from '../api/init';
|
||||
@@ -5,10 +8,9 @@ import * as supertest from 'supertest';
|
||||
import { startEventServer } from '../event-stream/event-server';
|
||||
import { Server } from 'net';
|
||||
import { createHash } from 'crypto';
|
||||
import { DbTx, DbTxStatus } from '../datastore/common';
|
||||
import { DbMempoolTx, DbTx, DbTxStatus } from '../datastore/common';
|
||||
import { AnchorMode, ChainID, PostConditionMode, someCV } from '@stacks/transactions';
|
||||
import { StacksMocknet } from '@stacks/network';
|
||||
import * as assert from 'assert';
|
||||
|
||||
import {
|
||||
broadcastTransaction,
|
||||
@@ -25,6 +27,7 @@ import BigNum = require('bn.js');
|
||||
import { logger } from '../helpers';
|
||||
import { testnetKeys } from '../api/routes/debug';
|
||||
import { importV1BnsData } from '../import-v1';
|
||||
import * as assert from 'assert';
|
||||
|
||||
function hash160(bfr: Buffer): Buffer {
|
||||
const hash160 = createHash('ripemd160')
|
||||
@@ -37,22 +40,12 @@ const network = new StacksMocknet();
|
||||
|
||||
const deployedTo = 'ST000000000000000000002AMW42H';
|
||||
const deployedName = 'bns';
|
||||
|
||||
const pkey = testnetKeys[0].secretKey;
|
||||
const address = testnetKeys[0].stacksAddress;
|
||||
const pkey1 = testnetKeys[1].secretKey;
|
||||
const address1 = testnetKeys[1].stacksAddress;
|
||||
const pkey2 = testnetKeys[2].secretKey;
|
||||
const address2 = testnetKeys[2].stacksAddress;
|
||||
|
||||
const salt = Buffer.from('60104ad42ed976f5b8cfd6341496476aa72d1101', 'hex'); // salt and pepper
|
||||
const namespace = 'foo';
|
||||
const namespaceHash = hash160(Buffer.concat([Buffer.from(namespace), salt]));
|
||||
const name = 'alice';
|
||||
const name1 = 'bob';
|
||||
const postConditions = [
|
||||
makeStandardSTXPostCondition(address, FungibleConditionCode.GreaterEqual, new BigNum(1)),
|
||||
];
|
||||
|
||||
type TestnetKey = {
|
||||
pkey: string;
|
||||
address: string;
|
||||
}
|
||||
|
||||
describe('BNS integration tests', () => {
|
||||
let db: PgDataStore;
|
||||
@@ -96,105 +89,12 @@ describe('BNS integration tests', () => {
|
||||
|
||||
return broadcastTx;
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
process.env.PG_DATABASE = 'postgres';
|
||||
await cycleMigrations();
|
||||
db = await PgDataStore.connect();
|
||||
client = await db.pool.connect();
|
||||
eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet, httpLogLevel: 'silly' });
|
||||
api = await startApiServer({ datastore: db, chainId: ChainID.Testnet, httpLogLevel: 'silly' });
|
||||
|
||||
//preorder and reveal namespace to the bns network
|
||||
while (true) {
|
||||
try {
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'namespace-preorder',
|
||||
functionArgs: [bufferCV(namespaceHash), uintCV(64000000000)],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
postConditions: postConditions,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const submitResult = await broadcastTransaction(transaction, network);
|
||||
const preorder = await standByForTx('0x' + transaction.txid());
|
||||
if (preorder.status != 1) logger.error('Namespace preorder error');
|
||||
|
||||
const revealTxOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'namespace-reveal',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(salt),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(20), //this number is set to expire the name before calling name-revewal
|
||||
standardPrincipalCV(address),
|
||||
],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
|
||||
const revealTransaction = await makeContractCall(revealTxOptions);
|
||||
await broadcastTransaction(revealTransaction, network);
|
||||
const reveal = await standByForTx('0x' + revealTransaction.txid());
|
||||
if (reveal.status != 1) logger.error('Namespace Reveal Error');
|
||||
|
||||
break;
|
||||
} catch (e) {
|
||||
console.log('error connection', e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('name-import contract call', async () => {
|
||||
const zonefile = `$ORIGIN ${name}.${namespace}\n$TTL 3600\n_http._tcp IN URI 10 1 "https://blockstack.s3.amazonaws.com/${name}.${namespace}"\n`;
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-import',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
standardPrincipalCV(address),
|
||||
bufferCV(hash160(Buffer.from(zonefile))),
|
||||
],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
async function getContractTransaction(txOptions: SignedContractCallOptions, zonefile?: string) {
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
attachment: Buffer.from(zonefile).toString('hex'),
|
||||
const body: {tx: string, attachment?: string} = {
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
};
|
||||
if(zonefile) body.attachment = Buffer.from(zonefile).toString('hex');
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
@@ -205,17 +105,84 @@ describe('BNS integration tests', () => {
|
||||
const result = await standByForTx(expectedTxId);
|
||||
if (result.status != 1) logger.error('name-import error');
|
||||
await standbyBnsName(expectedTxId);
|
||||
const query = await db.getName({ name: `${name}.${namespace}`, includeUnanchored: false });
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
expect(query.found).toBe(true);
|
||||
if (query.found) {
|
||||
expect(query.result.zonefile).toBe(zonefile);
|
||||
}
|
||||
});
|
||||
return transaction;
|
||||
}
|
||||
async function namespacePreorder(namespaceHash: Buffer, testnetKey: TestnetKey) {
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'namespace-preorder',
|
||||
functionArgs: [bufferCV(namespaceHash), uintCV(64000000000)],
|
||||
senderKey: testnetKey.pkey,
|
||||
validateWithAbi: true,
|
||||
postConditions: [makeStandardSTXPostCondition(testnetKey.address, FungibleConditionCode.GreaterEqual, new BigNum(1))],
|
||||
network,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
|
||||
test('namespace-ready contract call', async () => {
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
await broadcastTransaction(transaction, network);
|
||||
const preorder = await standByForTx('0x' + transaction.txid());
|
||||
if (preorder.status != 1) logger.error('Namespace preorder error');
|
||||
|
||||
return transaction;
|
||||
}
|
||||
async function namespaceReveal(namespace: string, salt: Buffer, testnetKey: TestnetKey, expiration: number) {
|
||||
const revealTxOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'namespace-reveal',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(salt),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(1),
|
||||
uintCV(expiration), //this number is set to expire the name before calling name-revewal
|
||||
standardPrincipalCV(testnetKey.address),
|
||||
],
|
||||
senderKey: testnetKey.pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
const revealTransaction = await makeContractCall(revealTxOptions);
|
||||
await broadcastTransaction(revealTransaction, network);
|
||||
const reveal = await standByForTx('0x' + revealTransaction.txid());
|
||||
if (reveal.status != 1) logger.error('Namespace Reveal Error');
|
||||
return revealTransaction;
|
||||
}
|
||||
async function initiateNamespaceNetwork(namespace: string, salt: Buffer, namespaceHash: Buffer, testnetKey: TestnetKey, expiration: number){
|
||||
while (true) {
|
||||
try {
|
||||
const preorderTransaction = await namespacePreorder(namespaceHash, testnetKey);
|
||||
|
||||
const revealTransaction = await namespaceReveal(namespace, salt, testnetKey, expiration);
|
||||
|
||||
break;
|
||||
} catch (e) {
|
||||
console.log('error connection', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
async function namespaceReady(namespace: string, pkey: string) {
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
@@ -224,24 +191,36 @@ describe('BNS integration tests', () => {
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
|
||||
const submitResult = await broadcastTransaction(transaction, network);
|
||||
await broadcastTransaction(transaction, network);
|
||||
|
||||
const readyResult = await standByForTx('0x' + transaction.txid());
|
||||
if (readyResult.status != 1) logger.error('namespace-ready error');
|
||||
const query1 = await supertest(api.server).get('/v1/namespaces');
|
||||
const result = JSON.parse(query1.text);
|
||||
expect(result.namespaces.includes(namespace)).toBe(true);
|
||||
});
|
||||
|
||||
test('name-update contract call', async () => {
|
||||
const zonefile = `$TTL 3600
|
||||
1yeardaily TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxeWVhcmRhaWx5CiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMXllYXJkYWlseS9oZWFkLmpzb24iCg=="
|
||||
_http._tcp URI 10 1 "https://dotpodcast.co/"`;
|
||||
return transaction;
|
||||
}
|
||||
async function nameImport(namespace: string, zonefile: string, name: string, testnetKey: TestnetKey) {
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-import',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
standardPrincipalCV(testnetKey.address),
|
||||
bufferCV(hash160(Buffer.from(zonefile))),
|
||||
],
|
||||
senderKey: testnetKey.pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
return await getContractTransaction(txOptions, zonefile);
|
||||
}
|
||||
async function nameUpdate(namespace: string, zonefile: string, name: string, pkey: string) {
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
@@ -254,33 +233,175 @@ describe('BNS integration tests', () => {
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
attachment: Buffer.from(zonefile).toString('hex'),
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
return await getContractTransaction(txOptions, zonefile);
|
||||
}
|
||||
async function namePreorder(namespace: string, saltName: string, testnetKey: TestnetKey, name: string) {
|
||||
const postConditions = [
|
||||
makeStandardSTXPostCondition(testnetKey.address, FungibleConditionCode.GreaterEqual, new BigNum(1)),
|
||||
];
|
||||
const fqn = `${name}.${namespace}${saltName}`;
|
||||
const nameSaltedHash = hash160(Buffer.from(fqn));
|
||||
const preOrderTxOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-preorder',
|
||||
functionArgs: [bufferCV(nameSaltedHash), uintCV(64000000000)],
|
||||
senderKey: testnetKey.pkey,
|
||||
validateWithAbi: true,
|
||||
postConditions: postConditions,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
|
||||
const preOrderTransaction = await makeContractCall(preOrderTxOptions);
|
||||
await broadcastTransaction(preOrderTransaction, network);
|
||||
const preorderResult = await standByForTx('0x' + preOrderTransaction.txid());
|
||||
return preOrderTransaction;
|
||||
}
|
||||
async function nameRegister(namespace: string, saltName: string, zonefile: string, testnetKey: TestnetKey, name: string) {
|
||||
await namePreorder(namespace, saltName, testnetKey, name);
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-register',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
bufferCV(Buffer.from(saltName)),
|
||||
bufferCV(hash160(Buffer.from(zonefile))),
|
||||
],
|
||||
senderKey: testnetKey.pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
return await getContractTransaction(txOptions, zonefile);
|
||||
}
|
||||
async function nameTransfer(namespace: string, name: string, testnetKey: TestnetKey) {
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-transfer',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
standardPrincipalCV(testnetKey.address),
|
||||
noneCV(),
|
||||
],
|
||||
senderKey: testnetKey.pkey,
|
||||
validateWithAbi: true,
|
||||
postConditionMode: PostConditionMode.Allow,
|
||||
anchorMode: AnchorMode.Any,
|
||||
network,
|
||||
};
|
||||
|
||||
return await getContractTransaction(txOptions);
|
||||
}
|
||||
async function nameRevoke(namespace: string, name: string, pkey: string) {
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-revoke',
|
||||
functionArgs: [bufferCV(Buffer.from(namespace)), bufferCV(Buffer.from(name))],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
return await getContractTransaction(txOptions);
|
||||
}
|
||||
async function nameRenewal(namespace: string, zonefile: string, pkey: string, name: string) {
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-renewal',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
uintCV(2560000),
|
||||
noneCV(),
|
||||
someCV(bufferCV(hash160(Buffer.from(zonefile)))),
|
||||
],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any
|
||||
};
|
||||
return await getContractTransaction(txOptions);
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
process.env.PG_DATABASE = 'postgres';
|
||||
await cycleMigrations();
|
||||
db = await PgDataStore.connect();
|
||||
client = await db.pool.connect();
|
||||
eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet, httpLogLevel: 'silly' });
|
||||
api = await startApiServer({ datastore: db, chainId: ChainID.Testnet, httpLogLevel: 'silly' });
|
||||
});
|
||||
|
||||
test('name-import/ready/update contract call', async () => {
|
||||
const namespace = 'name-import';
|
||||
const name = 'alice';
|
||||
const importZonefile = `$ORIGIN ${name}.${namespace}\n$TTL 3600\n_http._tcp IN URI 10 1 "https://blockstack.s3.amazonaws.com/${name}.${namespace}"\n`;
|
||||
const namespaceHash = hash160(Buffer.concat([Buffer.from(namespace), salt]));
|
||||
const testnetKey = { pkey: testnetKeys[0].secretKey, address: testnetKeys[0].stacksAddress};
|
||||
|
||||
// initalizing namespace network - preorder and reveal
|
||||
await initiateNamespaceNetwork(namespace, salt, namespaceHash, testnetKey, 12);
|
||||
|
||||
// testing name import
|
||||
await nameImport(namespace, importZonefile, name, testnetKey);
|
||||
|
||||
const importQuery = await db.getName({ name: `${name}.${namespace}`, includeUnanchored: false });
|
||||
const importQuery1 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(importQuery1.status).toBe(200);
|
||||
expect(importQuery1.type).toBe('application/json');
|
||||
expect(importQuery.found).toBe(true);
|
||||
if (importQuery.found) {
|
||||
expect(importQuery.result.zonefile).toBe(importZonefile);
|
||||
}
|
||||
|
||||
// testing namespace ready
|
||||
await namespaceReady(namespace, testnetKey.pkey);
|
||||
|
||||
const readyQuery1 = await supertest(api.server).get('/v1/namespaces');
|
||||
const readyResult = JSON.parse(readyQuery1.text);
|
||||
expect(readyResult.namespaces.includes(namespace)).toBe(true);
|
||||
});
|
||||
|
||||
test('name-update contract call', async () => {
|
||||
const namespace = 'name-update';
|
||||
const name = 'update';
|
||||
const importZonefile = `$ORIGIN ${name}.${namespace}\n$TTL 3600\n_http._tcp IN URI 10 1 "https://blockstack.s3.amazonaws.com/${name}.${namespace}"\n`;
|
||||
const namespaceHash = hash160(Buffer.concat([Buffer.from(namespace), salt]));
|
||||
const testnetKey = { pkey: testnetKeys[1].secretKey, address: testnetKeys[1].stacksAddress};
|
||||
|
||||
// initalizing namespace network - preorder and reveal
|
||||
await initiateNamespaceNetwork(namespace, salt, namespaceHash, testnetKey, 12);
|
||||
|
||||
// testing name import
|
||||
await nameImport(namespace, importZonefile, name, testnetKey);
|
||||
|
||||
await namespaceReady(namespace, testnetKey.pkey);
|
||||
|
||||
// testing name update 1
|
||||
let zonefile = `$TTL 3600
|
||||
1yeardaily TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxeWVhcmRhaWx5CiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMXllYXJkYWlseS9oZWFkLmpzb24iCg=="
|
||||
_http._tcp URI 10 1 "https://dotpodcast.co/"`;
|
||||
|
||||
try {
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const submitResult = await apiResult.json();
|
||||
const expectedTxId = '0x' + transaction.txid();
|
||||
const result = await standByForTx(expectedTxId);
|
||||
await standbyBnsName(expectedTxId);
|
||||
if (result.status != 1) logger.error('name-update error');
|
||||
// testing name update
|
||||
await nameUpdate(namespace, zonefile, name, testnetKey.pkey);
|
||||
const query1 = await supertest(api.server).get(`/v1/names/1yeardaily.${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
const query2 = await db.getSubdomain({ subdomain: `1yeardaily.${name}.${namespace}`, includeUnanchored: false });
|
||||
assert(query2.found);
|
||||
expect(query2.result.resolver).toBe('');
|
||||
expect(query2.found).toBe(true);
|
||||
if(query2.result)
|
||||
expect(query2.result.resolver).toBe('');
|
||||
|
||||
const query3 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query3.status).toBe(200);
|
||||
@@ -289,10 +410,8 @@ describe('BNS integration tests', () => {
|
||||
} catch (err: any) {
|
||||
throw new Error('Error post transaction: ' + err.message);
|
||||
}
|
||||
});
|
||||
|
||||
test('name-update contract call 1', async () => {
|
||||
const zonefile = `$TTL 3600
|
||||
// testing name update 2
|
||||
zonefile = `$TTL 3600
|
||||
1yeardaily TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxeWVhcmRhaWx5CiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMXllYXJkYWlseS9oZWFkLmpzb24iCg=="Í
|
||||
2dopequeens TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAyZG9wZXF1ZWVucwokVFRMIDM2MDAKX2h0dHAuX3RjcCBVUkkgMTAgMSAiaHR0cHM6Ly9waC5kb3Rwb2RjYXN0LmNvLzJkb3BlcXVlZW5zL2hlYWQuanNvbiIK"
|
||||
10happier TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMGhhcHBpZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMGhhcHBpZXIvaGVhZC5qc29uIgo="
|
||||
@@ -303,38 +422,7 @@ describe('BNS integration tests', () => {
|
||||
10minuteteacher TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMG1pbnV0ZXRlYWNoZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMG1pbnV0ZXRlYWNoZXIvaGVhZC5qc29uIgo="
|
||||
36questionsthepodcastmusical TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzNnF1ZXN0aW9uc3RoZXBvZGNhc3RtdXNpY2FsCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzZxdWVzdGlvbnN0aGVwb2RjYXN0bXVzaWNhbC9oZWFkLmpzb24iCg=="
|
||||
_http._tcp URI 10 1 "https://dotpodcast.co/"`;
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-update',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
bufferCV(hash160(Buffer.from(zonefile))),
|
||||
],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
attachment: Buffer.from(zonefile).toString('hex'),
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
};
|
||||
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const submitResult = await apiResult.json();
|
||||
const expectedTxId = '0x' + transaction.txid();
|
||||
const result = await standByForTx(expectedTxId);
|
||||
await standbyBnsName(expectedTxId);
|
||||
if (result.status != 1) logger.error('name-update error');
|
||||
await nameUpdate(namespace, zonefile, name, testnetKey.pkey);
|
||||
const query1 = await supertest(api.server).get(`/v1/names/2dopequeens.${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
@@ -358,176 +446,59 @@ describe('BNS integration tests', () => {
|
||||
const query5 = await supertest(api.server).get(`/v1/names/excluded.${name}.${namespace}`);
|
||||
expect(query5.status).toBe(404);
|
||||
expect(query5.type).toBe('application/json');
|
||||
});
|
||||
|
||||
test('name-update contract call 2', async () => {
|
||||
const zonefile = `$TTL 3600
|
||||
// testing nameupdate 3
|
||||
zonefile = `$TTL 3600
|
||||
_http._tcp URI 10 1 "https://dotpodcast.co/"`;
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-update',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
bufferCV(hash160(Buffer.from(zonefile))),
|
||||
],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
attachment: Buffer.from(zonefile).toString('hex'),
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
};
|
||||
await nameUpdate(namespace, zonefile, name, testnetKey.pkey);
|
||||
|
||||
try {
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const submitResult = await apiResult.json();
|
||||
const expectedTxId = '0x' + transaction.txid();
|
||||
const result = await standByForTx(expectedTxId);
|
||||
await standbyBnsName(expectedTxId);
|
||||
if (result.status != 1) logger.error('name-update error');
|
||||
const query1 = await supertest(api.server).get(`/v1/names/2dopequeens.${name}.${namespace}`); //check if previous sobdomains are still there
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
const query2 = await db.getSubdomainsList({ page: 0, includeUnanchored: false });
|
||||
expect(query2.results).toContain(`1yeardaily.${name}.${namespace}`);
|
||||
const query3 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query3.status).toBe(200);
|
||||
expect(query3.type).toBe('application/json');
|
||||
expect(query3.body.zonefile).toBe(zonefile);
|
||||
const query6 = await supertest(api.server).get(`/v1/names/2dopequeens.${name}.${namespace}`); //check if previous sobdomains are still there
|
||||
expect(query6.status).toBe(200);
|
||||
expect(query6.type).toBe('application/json');
|
||||
const query7 = await db.getSubdomainsList({ page: 0, includeUnanchored: false });
|
||||
expect(query7.results).toContain(`1yeardaily.${name}.${namespace}`);
|
||||
const query8 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query8.status).toBe(200);
|
||||
expect(query8.type).toBe('application/json');
|
||||
expect(query8.body.zonefile).toBe(zonefile);
|
||||
} catch (err: any) {
|
||||
throw new Error('Error post transaction: ' + err.message);
|
||||
}
|
||||
});
|
||||
|
||||
test('name-register contract call', async () => {
|
||||
const postConditions = [
|
||||
makeStandardSTXPostCondition(address1, FungibleConditionCode.GreaterEqual, new BigNum(1)),
|
||||
];
|
||||
//name pre-order
|
||||
test('name-register/transfer contract call', async () => {
|
||||
const saltName = '0000';
|
||||
const fqn = `${name1}.${namespace}${saltName}`;
|
||||
const nameSaltedHash = hash160(Buffer.from(fqn));
|
||||
const preOrderTxOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-preorder',
|
||||
functionArgs: [bufferCV(nameSaltedHash), uintCV(64000000000)],
|
||||
senderKey: pkey1,
|
||||
validateWithAbi: true,
|
||||
postConditions: postConditions,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
const name = 'bob';
|
||||
const namespace = 'name-register';
|
||||
const namespaceHash = hash160(Buffer.concat([Buffer.from(namespace), salt]));
|
||||
const zonefile = `$ORIGIN ${name}.${namespace}\n$TTL 3600\n_http._tcp IN URI 10 1 "https://blockstack.s3.amazonaws.com/${name}.${namespace}"\n`;
|
||||
const importZonefile = `$ORIGIN ${name}.${namespace}\n$TTL 3600\n_http._tcp IN URI 10 1 "https://blockstack.s3.amazonaws.com/${name}.${namespace}"\n`;
|
||||
const testnetKey = { pkey: testnetKeys[2].secretKey, address: testnetKeys[2].stacksAddress};
|
||||
// initializing namespace network
|
||||
await initiateNamespaceNetwork(namespace, salt, namespaceHash, testnetKey, 12);
|
||||
await namespaceReady(namespace, testnetKey.pkey);
|
||||
|
||||
const preOrderTransaction = await makeContractCall(preOrderTxOptions);
|
||||
const broadcastTxResult = await broadcastTransaction(preOrderTransaction, network);
|
||||
const preorderResult = await standByForTx('0x' + preOrderTransaction.txid());
|
||||
//name register
|
||||
const zonefile = `$ORIGIN ${name1}.${namespace}\n$TTL 3600\n_http._tcp IN URI 10 1 "https://blockstack.s3.amazonaws.com/${name1}.${namespace}"\n`;
|
||||
const txOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-register',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name1)),
|
||||
bufferCV(Buffer.from(saltName)),
|
||||
bufferCV(hash160(Buffer.from(zonefile))),
|
||||
],
|
||||
senderKey: pkey1,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
attachment: Buffer.from(zonefile).toString('hex'),
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
};
|
||||
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const submitResult = await apiResult.json();
|
||||
|
||||
const expectedTxId = '0x' + transaction.txid();
|
||||
const result = await standByForTx(expectedTxId);
|
||||
await standbyBnsName(expectedTxId);
|
||||
if (result.status != 1) logger.error('name-register error');
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name1}.${namespace}`);
|
||||
// testing name register
|
||||
await nameRegister(namespace, saltName, zonefile, testnetKey, name);
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
const query = await db.getName({ name: `${name1}.${namespace}`, includeUnanchored: false });
|
||||
const query = await db.getName({ name: `${name}.${namespace}`, includeUnanchored: false });
|
||||
expect(query.found).toBe(true);
|
||||
if (query.found) {
|
||||
expect(query.result.zonefile).toBe(zonefile);
|
||||
}
|
||||
});
|
||||
|
||||
test('name-transfer contract call', async () => {
|
||||
//name owned by address before calling name-transfer
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
expect(query1.body.address).toBe(address);
|
||||
|
||||
//name transfer
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-transfer',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name)),
|
||||
standardPrincipalCV(address2),
|
||||
noneCV(),
|
||||
],
|
||||
senderKey: pkey,
|
||||
validateWithAbi: true,
|
||||
postConditionMode: PostConditionMode.Allow,
|
||||
anchorMode: AnchorMode.Any,
|
||||
network,
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
};
|
||||
// testing name transfer
|
||||
const transferTestnetKey = { pkey: testnetKeys[2].secretKey, address: testnetKeys[3].stacksAddress};
|
||||
await nameTransfer(namespace, name, transferTestnetKey);
|
||||
|
||||
try {
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const submitResult = await apiResult.json();
|
||||
|
||||
const expectedTxId = '0x' + transaction.txid();
|
||||
const result = await standByForTx(expectedTxId);
|
||||
await standbyBnsName(expectedTxId);
|
||||
if (result.status != 1) logger.error('name-transfer error');
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
expect(query1.body.zonefile).toBe('');
|
||||
expect(query1.body.status).toBe('name-transfer');
|
||||
expect(query1.body.address).toBe(address2);
|
||||
} catch (err: any) {
|
||||
throw new Error('Error post transaction: ' + err.message);
|
||||
}
|
||||
@@ -535,35 +506,19 @@ describe('BNS integration tests', () => {
|
||||
|
||||
test('name-revoke contract call', async () => {
|
||||
//name revoke
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-revoke',
|
||||
functionArgs: [bufferCV(Buffer.from(namespace)), bufferCV(Buffer.from(name))],
|
||||
senderKey: pkey2,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
const namespace = 'name-revoke';
|
||||
const name = 'foo';
|
||||
const namespaceHash = hash160(Buffer.concat([Buffer.from(namespace), salt]));
|
||||
const testnetKey = { pkey: testnetKeys[4].secretKey, address: testnetKeys[4].stacksAddress};
|
||||
const zonefile = `$ORIGIN ${name}.${namespace}\n$TTL 3600\n_http._tcp IN URI 10 1 "https://blockstack.s3.amazonaws.com/${name}.${namespace}"\n`;
|
||||
|
||||
// initializing namespace network
|
||||
await initiateNamespaceNetwork(namespace, salt, namespaceHash, testnetKey, 12);
|
||||
await nameImport(namespace, zonefile, name, testnetKey);
|
||||
await namespaceReady(namespace, testnetKey.pkey);
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
};
|
||||
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const submitResult = await apiResult.json();
|
||||
const expectedTxId = '0x' + transaction.txid();
|
||||
const result = await standByForTx(expectedTxId);
|
||||
await standbyBnsName(expectedTxId);
|
||||
if (result.status !== 1) {
|
||||
throw new Error('name-revoke error');
|
||||
}
|
||||
// testing name revoke
|
||||
const transaction = await nameRevoke(namespace, name, testnetKey.pkey);
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
@@ -572,43 +527,20 @@ describe('BNS integration tests', () => {
|
||||
|
||||
test('name-renewal contract call', async () => {
|
||||
const zonefile = `new zone file`;
|
||||
const namespace = 'name-renewal';
|
||||
const name = 'renewal';
|
||||
const namespaceHash = hash160(Buffer.concat([Buffer.from(namespace), salt]));
|
||||
const testnetKey = { pkey: testnetKeys[5].secretKey, address: testnetKeys[5].stacksAddress};
|
||||
|
||||
// initializing namespace network
|
||||
await initiateNamespaceNetwork(namespace, salt, namespaceHash, testnetKey, 1);
|
||||
await nameImport(namespace, zonefile, name, testnetKey);
|
||||
await namespaceReady(namespace, testnetKey.pkey);
|
||||
|
||||
//name renewal
|
||||
const txOptions: SignedContractCallOptions = {
|
||||
contractAddress: deployedTo,
|
||||
contractName: deployedName,
|
||||
functionName: 'name-renewal',
|
||||
functionArgs: [
|
||||
bufferCV(Buffer.from(namespace)),
|
||||
bufferCV(Buffer.from(name1)),
|
||||
uintCV(2560000),
|
||||
noneCV(),
|
||||
someCV(bufferCV(hash160(Buffer.from(zonefile)))),
|
||||
],
|
||||
senderKey: pkey1,
|
||||
validateWithAbi: true,
|
||||
network,
|
||||
anchorMode: AnchorMode.Any,
|
||||
};
|
||||
|
||||
const transaction = await makeContractCall(txOptions);
|
||||
const body = {
|
||||
attachment: Buffer.from(zonefile).toString('hex'),
|
||||
tx: transaction.serialize().toString('hex'),
|
||||
};
|
||||
|
||||
await nameRenewal(namespace, zonefile, testnetKey.pkey, name);
|
||||
try {
|
||||
const apiResult = await fetch(network.getBroadcastApiUrl(), {
|
||||
method: 'post',
|
||||
body: JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const submitResult = await apiResult.json();
|
||||
const expectedTxId = '0x' + transaction.txid();
|
||||
const result = await standByForTx(expectedTxId);
|
||||
await standbyBnsName(expectedTxId);
|
||||
if (result.status != 1) logger.error('name-renewal: error');
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name1}.${namespace}`);
|
||||
const query1 = await supertest(api.server).get(`/v1/names/${name}.${namespace}`);
|
||||
expect(query1.status).toBe(200);
|
||||
expect(query1.type).toBe('application/json');
|
||||
expect(query1.body.zonefile).toBe(zonefile);
|
||||
@@ -653,7 +585,8 @@ describe('BNS integration tests', () => {
|
||||
|
||||
const dbquery = await db.getSubdomain({ subdomain: `flushreset.id.blockstack`, includeUnanchored: false });
|
||||
assert(dbquery.found)
|
||||
expect(dbquery.result.name).toBe('id.blockstack');
|
||||
if (dbquery.result){
|
||||
expect(dbquery.result.name).toBe('id.blockstack');}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -664,3 +597,4 @@ describe('BNS integration tests', () => {
|
||||
await runMigrations(undefined, 'down');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -27,3 +27,13 @@ amount = 10000000000000000
|
||||
address = "STRYYQQ9M8KAF4NS7WNZQYY59X93XEKR31JP64CP"
|
||||
amount = 10000000000000000
|
||||
# secretKey = "e75dcb66f84287eaf347955e94fa04337298dbd95aa0dbb985771104ef1913db01"
|
||||
|
||||
[[mstx_balance]]
|
||||
address = "STF9B75ADQAVXQHNEQ6KGHXTG7JP305J2GRWF3A2"
|
||||
amount = 10000000000000000
|
||||
# secretKey = "ce109fee08860bb16337c76647dcbc02df0c06b455dd69bcf30af74d4eedd19301"
|
||||
|
||||
[[mstx_balance]]
|
||||
address = "ST18MDW2PDTBSCR1ACXYRJP2JX70FWNM6YY2VX4SS"
|
||||
amount = 10000000000000000
|
||||
# secretKey = "08c14a1eada0dd42b667b40f59f7c8dedb12113613448dc04980aea20b268ddb01"
|
||||
|
||||
Reference in New Issue
Block a user