diff --git a/src/api/routes/debug.ts b/src/api/routes/debug.ts index f12cb7ed..343255cf 100644 --- a/src/api/routes/debug.ts +++ b/src/api/routes/debug.ts @@ -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< diff --git a/src/tests-bns/bns-integration-tests.ts b/src/tests-bns/bns-integration-tests.ts index 15812abb..b58eb9fd 100644 --- a/src/tests-bns/bns-integration-tests.ts +++ b/src/tests-bns/bns-integration-tests.ts @@ -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'); }); }); + diff --git a/stacks-blockchain/Stacks-dev.toml b/stacks-blockchain/Stacks-dev.toml index b09470b7..53ee9136 100644 --- a/stacks-blockchain/Stacks-dev.toml +++ b/stacks-blockchain/Stacks-dev.toml @@ -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"