Skip to content

Commit

Permalink
Add PlatformAddress and its tests
Browse files Browse the repository at this point in the history
  • Loading branch information
joojis committed Jun 26, 2018
1 parent 3025a98 commit 4e84f38
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
50 changes: 50 additions & 0 deletions src/PlatformAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { H160 } from "./primitives/H160";
import { toWords, encode, decode, fromWords } from "./bech32";
import { toHex } from "./utils";

/**
* Substitutes for platform token owner which consists of network id and account
* id. . The network id is represented with prefix "ccc"(mainnet) or
* "tcc"(testnet). Currently version 0 exists only.
*
* Refer to the wiki for the details about PlatformAddress.
* https://github.com/CodeChain-io/codechain/wiki/CodeChain-Address
*/
export class PlatformAddress {
accountId: H160;

value: string;

private constructor(accountId: H160, address: string) {
this.accountId = accountId;
this.value = address;
}

static fromAccountId(accountId: H160, options: { isTestnet?: boolean, version?: number } = {}) {
const { isTestnet = false, version = 0 } = options;

if (version !== 0) {
throw `Unsupported version for platform address: ${version}`;
}

const words = toWords(Buffer.from([version, ...Buffer.from(accountId.value, "hex")]));
return new PlatformAddress(accountId, encode(isTestnet ? "tcc" : "ccc", words));
}

static fromAddress(address: string) {
if (!address.startsWith("ccc") && !address.startsWith("tcc")) {
throw `The prefix is unknown for platform address: ${address}`;
}

const { words } = decode(address, address.substr(0, 3));
const bytes = fromWords(words);
const version = bytes[0];

if (version !== 0) {
throw `Unsupported version for platform address: ${version}`;
}

const accountId = toHex(Buffer.from(bytes.slice(1)));
return new PlatformAddress(new H160(accountId), address);
}
}
44 changes: 44 additions & 0 deletions src/__test__/PlatformAddress.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { PlatformAddress } from "../PlatformAddress";
import { H160 } from "../primitives/H160";

test("PlatformAddress.fromAccountId - mainnet (default)", () => {
const accountId = new H160("7b5e0ee8644c6f585fc297364143280a45844502");
const address = PlatformAddress.fromAccountId(accountId);
expect(address.value).toMatch(/^ccc[a-z0-9]+$/);
});

test("PlatformAddress.fromAccountId - testnet", () => {
const accountId = new H160("7b5e0ee8644c6f585fc297364143280a45844502");
const address = PlatformAddress.fromAccountId(accountId, { isTestnet: true });
expect(address.value).toMatch(/^tcc[a-z0-9]+$/);
});

test("PlatformAddress.fromAccountId - valid version", () => {
const accountId = new H160("7b5e0ee8644c6f585fc297364143280a45844502");
expect(() => {
PlatformAddress.fromAccountId(accountId, { version: 0 });
}).not.toThrow();
});

test("PlatformAddress.fromAccountId - invalid version", () => {
const accountId = new H160("7b5e0ee8644c6f585fc297364143280a45844502");
expect(() => {
PlatformAddress.fromAccountId(accountId, { version: 1 });
}).toThrow("Unsupported version for platform address: 1");
});

test("PlatformAddress.fromAddress - mainnet", () => {
const address = PlatformAddress.fromAddress("cccqpa4urhgv3xx7kzlc2tnvs2r9q9ytpz9qg4aw2qm");
expect(address.accountId).toEqual(new H160("7b5e0ee8644c6f585fc297364143280a45844502"));
});

test("PlatformAddress.fromAddress - testnet", () => {
const address = PlatformAddress.fromAddress("tccqpa4urhgv3xx7kzlc2tnvs2r9q9ytpz9qga6ufnz");
expect(address.accountId).toEqual(new H160("7b5e0ee8644c6f585fc297364143280a45844502"));
});

test("PlatformAddress.fromAddress - invalid checksum", () => {
expect(() => {
PlatformAddress.fromAddress("cccqpa4urhgv3xx7kzlc2tnvs2r9q9ytpz9qgqqqqqq");
}).toThrow();
});
4 changes: 2 additions & 2 deletions src/bech32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,6 @@ export function toWords (bytes: any) {
}

// FIXME: any
function fromWords (words: any) {
export function fromWords (words: any) {
return convert(words, 5, 8, false);
}
}
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const secp256k1 = new EC("secp256k1");

const toHexByte = (byte: number) => byte < 0x10 ? `0${byte.toString(16)}` : byte.toString(16);

const toHex = (buffer: Buffer): string => {
export const toHex = (buffer: Buffer): string => {
return Array.from(buffer).map(toHexByte).join("");
};

Expand Down

0 comments on commit 4e84f38

Please sign in to comment.