@iyonger/aptos-web3-bip44.js
Version:
Web3 SDK For Aptos
343 lines (285 loc) • 13.1 kB
text/typescript
// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0
import { HexString } from "../hex_string";
import {
AccountAddress,
Identifier,
StructTag,
TransactionArgumentAddress,
TransactionArgumentBool,
TransactionArgumentU128,
TransactionArgumentU64,
TransactionArgumentU8,
TransactionArgumentU8Vector,
TypeTagAddress,
TypeTagBool,
TypeTagStruct,
TypeTagU128,
TypeTagU64,
TypeTagU8,
TypeTagVector,
} from "../aptos_types";
import { Serializer } from "../bcs";
import {
argToTransactionArgument,
TypeTagParser,
serializeArg,
ensureBoolean,
ensureNumber,
ensureBigInt,
} from "./builder_utils";
describe("BuilderUtils", () => {
it("parses a bool TypeTag", async () => {
expect(new TypeTagParser("bool").parseTypeTag() instanceof TypeTagBool).toBeTruthy();
});
it("parses a u8 TypeTag", async () => {
expect(new TypeTagParser("u8").parseTypeTag() instanceof TypeTagU8).toBeTruthy();
});
it("parses a u64 TypeTag", async () => {
expect(new TypeTagParser("u64").parseTypeTag() instanceof TypeTagU64).toBeTruthy();
});
it("parses a u128 TypeTag", async () => {
expect(new TypeTagParser("u128").parseTypeTag() instanceof TypeTagU128).toBeTruthy();
});
it("parses a address TypeTag", async () => {
expect(new TypeTagParser("address").parseTypeTag() instanceof TypeTagAddress).toBeTruthy();
});
it("parses a vector TypeTag", async () => {
const vectorAddress = new TypeTagParser("vector<address>").parseTypeTag();
expect(vectorAddress instanceof TypeTagVector).toBeTruthy();
expect((vectorAddress as TypeTagVector).value instanceof TypeTagAddress).toBeTruthy();
const vectorU64 = new TypeTagParser(" vector < u64 > ").parseTypeTag();
expect(vectorU64 instanceof TypeTagVector).toBeTruthy();
expect((vectorU64 as TypeTagVector).value instanceof TypeTagU64).toBeTruthy();
});
it("parses a sturct TypeTag", async () => {
const assertStruct = (struct: TypeTagStruct, accountAddress: string, moduleName: string, structName: string) => {
expect(HexString.fromUint8Array(struct.value.address.address).toShortString()).toBe(accountAddress);
expect(struct.value.module_name.value).toBe(moduleName);
expect(struct.value.name.value).toBe(structName);
};
const coin = new TypeTagParser("0x1::test_coin::Coin").parseTypeTag();
expect(coin instanceof TypeTagStruct).toBeTruthy();
assertStruct(coin as TypeTagStruct, "0x1", "test_coin", "Coin");
const aptosCoin = new TypeTagParser(
"0x1::coin::CoinStore < 0x1::test_coin::AptosCoin1 , 0x1::test_coin::AptosCoin2 > ",
).parseTypeTag();
expect(aptosCoin instanceof TypeTagStruct).toBeTruthy();
assertStruct(aptosCoin as TypeTagStruct, "0x1", "coin", "CoinStore");
const aptosCoinTrailingComma = new TypeTagParser(
"0x1::coin::CoinStore < 0x1::test_coin::AptosCoin1 , 0x1::test_coin::AptosCoin2, > ",
).parseTypeTag();
expect(aptosCoinTrailingComma instanceof TypeTagStruct).toBeTruthy();
assertStruct(aptosCoinTrailingComma as TypeTagStruct, "0x1", "coin", "CoinStore");
const structTypeTags = (aptosCoin as TypeTagStruct).value.type_args;
expect(structTypeTags.length).toBe(2);
const structTypeTag1 = structTypeTags[0];
assertStruct(structTypeTag1 as TypeTagStruct, "0x1", "test_coin", "AptosCoin1");
const structTypeTag2 = structTypeTags[1];
assertStruct(structTypeTag2 as TypeTagStruct, "0x1", "test_coin", "AptosCoin2");
const coinComplex = new TypeTagParser(
// eslint-disable-next-line max-len
"0x1::coin::CoinStore < 0x2::coin::LPCoin < 0x1::test_coin::AptosCoin1 <u8>, vector<0x1::test_coin::AptosCoin2 > > >",
).parseTypeTag();
expect(coinComplex instanceof TypeTagStruct).toBeTruthy();
assertStruct(coinComplex as TypeTagStruct, "0x1", "coin", "CoinStore");
const coinComplexTypeTag = (coinComplex as TypeTagStruct).value.type_args[0];
assertStruct(coinComplexTypeTag as TypeTagStruct, "0x2", "coin", "LPCoin");
expect(() => {
new TypeTagParser("0x1::test_coin").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("0x1::test_coin::CoinStore<0x1::test_coin::AptosCoin").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("0x1::test_coin::CoinStore<0x1::test_coin>").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("0x1:test_coin::AptosCoin").parseTypeTag();
}).toThrow("Unrecognized token.");
expect(() => {
new TypeTagParser("0x!::test_coin::AptosCoin").parseTypeTag();
}).toThrow("Unrecognized token.");
expect(() => {
new TypeTagParser("0x1::test_coin::AptosCoin<").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("0x1::test_coin::CoinStore<0x1::test_coin::AptosCoin,").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("0x1::<::CoinStore<0x1::test_coin::AptosCoin,").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("0x1::test_coin::><0x1::test_coin::AptosCoin,").parseTypeTag();
}).toThrow("Invalid type tag.");
expect(() => {
new TypeTagParser("u32").parseTypeTag();
}).toThrow("Invalid type tag.");
});
it("serializes a boolean arg", async () => {
let serializer = new Serializer();
serializeArg(true, new TypeTagBool(), serializer);
expect(serializer.getBytes()).toEqual(new Uint8Array([0x01]));
serializer = new Serializer();
expect(() => {
serializeArg(123, new TypeTagBool(), serializer);
}).toThrow(/Invalid arg/);
});
it("serializes a u8 arg", async () => {
let serializer = new Serializer();
serializeArg(255, new TypeTagU8(), serializer);
expect(serializer.getBytes()).toEqual(new Uint8Array([0xff]));
serializer = new Serializer();
expect(() => {
serializeArg("u8", new TypeTagU8(), serializer);
}).toThrow(/Invalid number string/);
});
it("serializes a u64 arg", async () => {
let serializer = new Serializer();
serializeArg(BigInt("18446744073709551615"), new TypeTagU64(), serializer);
expect(serializer.getBytes()).toEqual(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]));
serializer = new Serializer();
expect(() => {
serializeArg("u64", new TypeTagU64(), serializer);
}).toThrow(/^Cannot convert/);
});
it("serializes a u128 arg", async () => {
let serializer = new Serializer();
serializeArg(BigInt("340282366920938463463374607431768211455"), new TypeTagU128(), serializer);
expect(serializer.getBytes()).toEqual(
new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
);
serializer = new Serializer();
expect(() => {
serializeArg("u128", new TypeTagU128(), serializer);
}).toThrow(/^Cannot convert/);
});
it("serializes an AccountAddress arg", async () => {
let serializer = new Serializer();
serializeArg("0x1", new TypeTagAddress(), serializer);
expect(HexString.fromUint8Array(serializer.getBytes()).toShortString()).toEqual("0x1");
serializer = new Serializer();
serializeArg(AccountAddress.fromHex("0x1"), new TypeTagAddress(), serializer);
expect(HexString.fromUint8Array(serializer.getBytes()).toShortString()).toEqual("0x1");
serializer = new Serializer();
expect(() => {
serializeArg(123456, new TypeTagAddress(), serializer);
}).toThrow("Invalid account address.");
});
it("serializes a vector arg", async () => {
let serializer = new Serializer();
serializeArg([255], new TypeTagVector(new TypeTagU8()), serializer);
expect(serializer.getBytes()).toEqual(new Uint8Array([0x1, 0xff]));
serializer = new Serializer();
serializeArg("abc", new TypeTagVector(new TypeTagU8()), serializer);
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x61, 0x62, 0x63]));
serializer = new Serializer();
serializeArg(new Uint8Array([0x61, 0x62, 0x63]), new TypeTagVector(new TypeTagU8()), serializer);
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x61, 0x62, 0x63]));
serializer = new Serializer();
expect(() => {
serializeArg(123456, new TypeTagVector(new TypeTagU8()), serializer);
}).toThrow("Invalid vector args.");
});
it("serializes a struct arg", async () => {
let serializer = new Serializer();
serializeArg(
"abc",
new TypeTagStruct(
new StructTag(AccountAddress.fromHex("0x1"), new Identifier("string"), new Identifier("String"), []),
),
serializer,
);
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x61, 0x62, 0x63]));
serializer = new Serializer();
expect(() => {
serializeArg(
"abc",
new TypeTagStruct(
new StructTag(AccountAddress.fromHex("0x3"), new Identifier("token"), new Identifier("Token"), []),
),
serializer,
);
}).toThrow("The only supported struct arg is of type 0x1::string::String");
});
it("throws at unrecognized arg types", async () => {
const serializer = new Serializer();
expect(() => {
// @ts-ignore
serializeArg(123456, "unknown_type", serializer);
}).toThrow("Unsupported arg type.");
});
it("converts a boolean TransactionArgument", async () => {
const res = argToTransactionArgument(true, new TypeTagBool());
expect((res as TransactionArgumentBool).value).toEqual(true);
expect(() => {
argToTransactionArgument(123, new TypeTagBool());
}).toThrow(/Invalid arg/);
});
it("converts a u8 TransactionArgument", async () => {
const res = argToTransactionArgument(123, new TypeTagU8());
expect((res as TransactionArgumentU8).value).toEqual(123);
expect(() => {
argToTransactionArgument("u8", new TypeTagBool());
}).toThrow(/Invalid boolean string/);
});
it("converts a u64 TransactionArgument", async () => {
const res = argToTransactionArgument(123, new TypeTagU64());
expect((res as TransactionArgumentU64).value).toEqual(BigInt(123));
expect(() => {
argToTransactionArgument("u64", new TypeTagU64());
}).toThrow(/Cannot convert/);
});
it("converts a u128 TransactionArgument", async () => {
const res = argToTransactionArgument(123, new TypeTagU128());
expect((res as TransactionArgumentU128).value).toEqual(BigInt(123));
expect(() => {
argToTransactionArgument("u128", new TypeTagU128());
}).toThrow(/Cannot convert/);
});
it("converts an AccountAddress TransactionArgument", async () => {
let res = argToTransactionArgument("0x1", new TypeTagAddress()) as TransactionArgumentAddress;
expect(HexString.fromUint8Array(res.value.address).toShortString()).toEqual("0x1");
res = argToTransactionArgument(AccountAddress.fromHex("0x2"), new TypeTagAddress()) as TransactionArgumentAddress;
expect(HexString.fromUint8Array(res.value.address).toShortString()).toEqual("0x2");
expect(() => {
argToTransactionArgument(123456, new TypeTagAddress());
}).toThrow("Invalid account address.");
});
it("converts a vector TransactionArgument", async () => {
const res = argToTransactionArgument(
new Uint8Array([0x1]),
new TypeTagVector(new TypeTagU8()),
) as TransactionArgumentU8Vector;
expect(res.value).toEqual(new Uint8Array([0x1]));
expect(() => {
argToTransactionArgument(123456, new TypeTagVector(new TypeTagU8()));
}).toThrow(/.*should be an instance of Uint8Array$/);
});
it("throws at unrecognized TransactionArgument types", async () => {
expect(() => {
// @ts-ignore
argToTransactionArgument(123456, "unknown_type");
}).toThrow("Unknown type for TransactionArgument.");
});
it("ensures a boolean", async () => {
expect(ensureBoolean(false)).toBe(false);
expect(ensureBoolean(true)).toBe(true);
expect(ensureBoolean("true")).toBe(true);
expect(ensureBoolean("false")).toBe(false);
expect(() => ensureBoolean("True")).toThrow("Invalid boolean string.");
});
it("ensures a number", async () => {
expect(ensureNumber(10)).toBe(10);
expect(ensureNumber("123")).toBe(123);
expect(() => ensureNumber("True")).toThrow("Invalid number string.");
});
it("ensures a bigint", async () => {
expect(ensureBigInt(10)).toBe(BigInt(10));
expect(ensureBigInt("123")).toBe(BigInt(123));
expect(() => ensureBigInt("True")).toThrow(/^Cannot convert/);
});
});