Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/pull-request-name-service.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,18 @@ jobs:
- name: Build and test
run: ./ci/cargo-test-sbf.sh name-service

- name: Upload programs
uses: actions/upload-artifact@v2
with:
name: name-service-programs
path: "target/deploy/*.so"
if-no-files-found: error

js-test:
runs-on: ubuntu-latest
env:
NODE_VERSION: 14.x
needs: cargo-test-sbf
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ env.NODE_VERSION }}
Expand All @@ -73,4 +81,9 @@ jobs:
key: node-${{ hashFiles('name-service/js/yarn.lock') }}
restore-keys: |
node-
- name: Download programs
uses: actions/download-artifact@v2
with:
name: name-service-programs
path: target/deploy
- run: ./ci/js-test-name-service.sh
1 change: 1 addition & 0 deletions ci/js-test-name-service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ cd name-service/js
yarn install --pure-lockfile
yarn lint
yarn build
yarn test
25 changes: 21 additions & 4 deletions name-service/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,36 @@
"prepublish": "tsc",
"lint": "yarn pretty && eslint --max-warnings 0 'src/*.ts'",
"lint:fix": "yarn pretty:fix && eslint 'src/*.ts' --fix",
"pretty": "prettier --check 'src/*.ts'",
"pretty:fix": "prettier --write 'src/*.ts'",
"doc": "yarn typedoc src/index.ts"
"pretty": "prettier --check '{src/*.ts,test/*/*.ts}'",
"pretty:fix": "prettier --write '{src/*.ts,test/*/*.ts}'",
"doc": "yarn typedoc src/index.ts",
"test": "yarn test:unit && yarn test:e2e",
"test:unit": "mocha test/unit",
"test:e2e": "start-server-and-test 'solana-test-validator --bpf-program namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX ../../target/deploy/spl_name_service.so --reset --quiet' http://localhost:8899/health 'mocha test/e2e'"
},
"prettier": {
"singleQuote": true
},
"devDependencies": {
"@tsconfig/recommended": "^1.0.1",
"@types/chai": "^4.3.4",
"@types/chai-as-promised": "^7.1.5",
"@types/mocha": "^10.0.1",
"@types/node": "^14.14.20",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"babel-eslint": "^10.1.0",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"mocha": "^10.2.0",
"prettier": "^2.2.1",
"ts-node": "^9.1.1",
"start-server-and-test": "^1.15.3",
"ts-node": "^10.9.1",
"typedoc": "^0.22.11",
"typescript": "^4.1.3"
},
Expand All @@ -51,5 +61,12 @@
"@solana/web3.js": "^1.11.0",
"bn.js": "^5.1.3",
"borsh": "^0.4.0"
},
"mocha": {
"require": [
"ts-node/register"
],
"recursive": true,
"extension": "ts"
}
}
132 changes: 132 additions & 0 deletions name-service/js/test/e2e/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import {
Connection,
Keypair,
LAMPORTS_PER_SOL,
PublicKey,
sendAndConfirmTransaction,
Transaction,
} from '@solana/web3.js';
import chai, { expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';

import {
createNameRegistry,
deleteNameRegistry,
getHashedName,
getNameAccountKey,
NameRegistryState,
reallocNameAccount,
transferNameOwnership,
updateNameRegistryData,
} from '../../src';

chai.use(chaiAsPromised);
const url = 'http://localhost:8899';

describe('Name Service Program', async () => {
const connection = new Connection(url, 'confirmed');
const payer = Keypair.generate();
const owner = Keypair.generate();
const space = 20;
let nameKey: PublicKey;
let name: string;
before(async () => {
const airdropSignature = await connection.requestAirdrop(
payer.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
signature: airdropSignature,
...(await connection.getLatestBlockhash()),
});
});

beforeEach(async () => {
name = Math.random().toString() + '.sol';
nameKey = await getNameKey(name);
const lamports = await connection.getMinimumBalanceForRentExemption(
space + NameRegistryState.HEADER_LEN
);
const inst = await createNameRegistry(
connection,
name,
space,
payer.publicKey,
owner.publicKey,
lamports
);
const tx = new Transaction().add(inst);
await sendAndConfirmTransaction(connection, tx, [payer]);
});

it('Create Name Registery', async () => {
const nameAccount = await NameRegistryState.retrieve(connection, nameKey);
nameAccount.owner.equals(owner.publicKey);
expect(nameAccount.data?.length).to.eql(space);
});
it('Update Name Registery', async () => {
const data = Buffer.from('@Dudl');
const inst = await updateNameRegistryData(connection, name, 0, data);
const tx = new Transaction().add(inst);
await sendAndConfirmTransaction(connection, tx, [payer, owner]);
const nameAccount = await NameRegistryState.retrieve(connection, nameKey);
nameAccount.data?.equals(data);
});
it('Transfer Name Ownership', async () => {
const newOwner = Keypair.generate();
const inst = await transferNameOwnership(
connection,
name,
newOwner.publicKey
);
const tx = new Transaction().add(inst);
await sendAndConfirmTransaction(connection, tx, [payer, owner]);
const nameAccount = await NameRegistryState.retrieve(connection, nameKey);
nameAccount.owner.equals(newOwner.publicKey);
});
it('Realloc Name Account to bigger space', async () => {
const inst = await reallocNameAccount(
connection,
name,
space + 10,
payer.publicKey
);
const tx = new Transaction().add(inst);
await sendAndConfirmTransaction(connection, tx, [payer, owner]);
const nameAccount = await NameRegistryState.retrieve(connection, nameKey);
expect(nameAccount.data?.length).to.eql(space + 10);
});
it('Realloc Name Account to smaller space', async () => {
const inst = await reallocNameAccount(
connection,
name,
space - 10,
payer.publicKey
);
const tx = new Transaction().add(inst);
await sendAndConfirmTransaction(connection, tx, [payer, owner]);
const nameAccount = await NameRegistryState.retrieve(connection, nameKey);
expect(nameAccount.data?.length).to.eql(space - 10);
});
it('Delete Name Registry', async () => {
const inst = await deleteNameRegistry(connection, name, payer.publicKey);
const tx = new Transaction().add(inst);
await sendAndConfirmTransaction(connection, tx, [payer, owner]);
const nameAccount = await connection.getAccountInfo(nameKey);
expect(nameAccount).to.be.null;
});
});

const getNameKey = async (
name: string,
nameClass?: PublicKey,
parentName?: PublicKey
) => {
const hashedName = await getHashedName(name);
const nameAccountKey = await getNameAccountKey(
hashedName,
nameClass,
parentName
);
return nameAccountKey;
};
139 changes: 139 additions & 0 deletions name-service/js/test/unit/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {
Keypair,
LAMPORTS_PER_SOL,
PublicKey,
SystemProgram,
} from '@solana/web3.js';
import chai, { expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';

import {
createInstruction,
deleteInstruction,
reallocInstruction,
transferInstruction,
updateInstruction,
} from '../../src';
import { Numberu32, Numberu64 } from '../../src/utils';

chai.use(chaiAsPromised);

describe('SplNameService Instructions', () => {
const nameServiceAddress = new PublicKey(
'namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX'
);
const nameAccountKey = Keypair.generate().publicKey;
const nameOwnerKey = Keypair.generate().publicKey;
const payerKey = Keypair.generate().publicKey;
const nameClassKey = Keypair.generate().publicKey;
const nameParent = Keypair.generate().publicKey;
const nameParentOwner = Keypair.generate().publicKey;
const name = Buffer.from('hello');

it('createInstruction without class and parent name key', () => {
const instruction = createInstruction(
nameServiceAddress,
SystemProgram.programId,
nameAccountKey,
nameOwnerKey,
payerKey,
name,
new Numberu64(LAMPORTS_PER_SOL),
new Numberu64(10)
);

expect(instruction.keys).to.have.length(6);
instruction.keys[0].pubkey.equals(SystemProgram.programId);
instruction.keys[1].pubkey.equals(payerKey);
instruction.keys[2].pubkey.equals(nameAccountKey);
instruction.keys[3].pubkey.equals(nameOwnerKey);
instruction.keys[4].pubkey.equals(new PublicKey(Buffer.alloc(32)));
instruction.keys[5].pubkey.equals(new PublicKey(Buffer.alloc(32)));
});

it('createInstruction with class and parent name key', () => {
const instruction = createInstruction(
nameServiceAddress,
SystemProgram.programId,
nameAccountKey,
nameOwnerKey,
payerKey,
name,
new Numberu64(LAMPORTS_PER_SOL),
new Numberu64(10),
nameClassKey,
nameParent,
nameParentOwner
);

expect(instruction.keys).to.have.length(7);
instruction.keys[0].pubkey.equals(SystemProgram.programId);
instruction.keys[1].pubkey.equals(payerKey);
instruction.keys[2].pubkey.equals(nameAccountKey);
instruction.keys[3].pubkey.equals(nameOwnerKey);
instruction.keys[4].pubkey.equals(nameClassKey);
instruction.keys[5].pubkey.equals(nameParent);
instruction.keys[6].pubkey.equals(nameParentOwner);
});

it('updateInstruction', () => {
const data = Buffer.from('@Dudl');
const instruction = updateInstruction(
nameServiceAddress,
nameAccountKey,
new Numberu32(0),
data,
nameOwnerKey,
undefined
);

expect(instruction.keys).to.have.length(2);
instruction.keys[0].pubkey.equals(nameAccountKey);
instruction.keys[1].pubkey.equals(nameOwnerKey);
});

it('transferInstruction', () => {
const newOwner = Keypair.generate().publicKey;
const instruction = transferInstruction(
nameServiceAddress,
nameAccountKey,
newOwner,
nameOwnerKey
);

expect(instruction.keys).to.have.length(2);
instruction.keys[0].pubkey.equals(nameAccountKey);
instruction.keys[1].pubkey.equals(nameOwnerKey);
});

it('deleteInstruction', () => {
const instruction = deleteInstruction(
nameServiceAddress,
nameAccountKey,
payerKey,
nameOwnerKey
);

expect(instruction.keys).to.have.length(3);
instruction.keys[0].pubkey.equals(nameAccountKey);
instruction.keys[1].pubkey.equals(nameOwnerKey);
instruction.keys[2].pubkey.equals(payerKey);
});

it('reallocInstruction', () => {
const instruction = reallocInstruction(
nameServiceAddress,
SystemProgram.programId,
payerKey,
nameAccountKey,
nameOwnerKey,
new Numberu32(30)
);

expect(instruction.keys).to.have.length(4);
instruction.keys[0].pubkey.equals(SystemProgram.programId);
instruction.keys[1].pubkey.equals(payerKey);
instruction.keys[2].pubkey.equals(nameAccountKey);
instruction.keys[3].pubkey.equals(nameOwnerKey);
});
});
Loading