@arkecosystem/typescript-crypto 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/enums/AbiFunction.d.ts +3 -1
  2. package/dist/enums/AbiFunction.d.ts.map +1 -1
  3. package/dist/enums/AbiFunction.js +2 -0
  4. package/dist/index.js +232 -96
  5. package/dist/transactions/builders/TokenTransferBuilder.d.ts +10 -0
  6. package/dist/transactions/builders/TokenTransferBuilder.d.ts.map +1 -0
  7. package/dist/transactions/builders/TokenTransferBuilder.js +25 -0
  8. package/dist/transactions/builders/index.d.ts +1 -0
  9. package/dist/transactions/builders/index.d.ts.map +1 -1
  10. package/dist/transactions/builders/index.js +1 -0
  11. package/dist/types.d.ts +5 -0
  12. package/dist/types.d.ts.map +1 -1
  13. package/dist/utils/AbiEncoder.d.ts +2 -0
  14. package/dist/utils/AbiEncoder.d.ts.map +1 -1
  15. package/dist/utils/AbiEncoder.js +3 -0
  16. package/dist/utils/Helpers.d.ts +8 -0
  17. package/dist/utils/Helpers.d.ts.map +1 -1
  18. package/dist/utils/Helpers.js +12 -0
  19. package/dist/utils/TransactionDataEncoder.d.ts +13 -0
  20. package/dist/utils/TransactionDataEncoder.d.ts.map +1 -0
  21. package/dist/utils/TransactionDataEncoder.js +44 -0
  22. package/dist/utils/TransactionTypeIdentifier.d.ts +24 -0
  23. package/dist/utils/TransactionTypeIdentifier.d.ts.map +1 -0
  24. package/dist/utils/TransactionTypeIdentifier.js +54 -0
  25. package/dist/utils/index.d.ts +2 -0
  26. package/dist/utils/index.d.ts.map +1 -1
  27. package/dist/utils/index.js +2 -0
  28. package/package.json +1 -1
  29. package/src/enums/AbiFunction.ts +2 -0
  30. package/src/transactions/builders/TokenTransferBuilder.ts +35 -0
  31. package/src/transactions/builders/index.ts +1 -0
  32. package/src/types.ts +7 -0
  33. package/src/utils/AbiEncoder.ts +5 -0
  34. package/src/utils/Helpers.ts +15 -0
  35. package/src/utils/TransactionDataEncoder.ts +54 -0
  36. package/src/utils/TransactionTypeIdentifier.ts +65 -0
  37. package/src/utils/index.ts +2 -0
  38. package/tests/fixtures/transactions/token-transfer.json +16 -0
  39. package/tests/fixtures/transactions/transaction-data-encoder.json +15 -0
  40. package/tests/unit/transactions/builders/TokenTransferBuilder.test.ts +138 -0
  41. package/tests/unit/utils/AbiEncoder.test.ts +12 -0
  42. package/tests/unit/utils/Helpers.test.ts +10 -0
  43. package/tests/unit/utils/TransactionDataEncoder.test.ts +51 -0
  44. package/tests/unit/utils/TransactionTypeIdentifier.test.ts +199 -0
@@ -0,0 +1,54 @@
1
+ import { ContractAbiType } from "@/enums";
2
+ import { AbiDecoder } from "./AbiDecoder";
3
+ import { ConsensusContract, MultipaymentContract, UsernamesContract } from "./Abi/json";
4
+ import { Helpers } from "./Helpers";
5
+ export const TransactionFunctionSigs = {
6
+ MultiPayment: MultipaymentContract.methodIdentifiers["pay(address[],uint256[])"],
7
+ RegisterUsername: UsernamesContract.methodIdentifiers["registerUsername(string)"],
8
+ ResignUsername: UsernamesContract.methodIdentifiers["resignUsername()"],
9
+ Transfer: "",
10
+ RegisterValidator: ConsensusContract.methodIdentifiers["registerValidator(bytes)"],
11
+ ResignValidator: ConsensusContract.methodIdentifiers["resignValidator()"],
12
+ Vote: ConsensusContract.methodIdentifiers["vote(address)"],
13
+ Unvote: ConsensusContract.methodIdentifiers["unvote()"],
14
+ UpdateValidator: ConsensusContract.methodIdentifiers["updateValidator(bytes)"],
15
+ };
16
+ export class TransactionTypeIdentifier {
17
+ static isTransfer(data) {
18
+ return data === TransactionFunctionSigs.Transfer;
19
+ }
20
+ static isVote(data) {
21
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.Vote);
22
+ }
23
+ static isUnvote(data) {
24
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.Unvote);
25
+ }
26
+ static isMultiPayment(data) {
27
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.MultiPayment);
28
+ }
29
+ static isUsernameRegistration(data) {
30
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.RegisterUsername);
31
+ }
32
+ static isUsernameResignation(data) {
33
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.ResignUsername);
34
+ }
35
+ static isValidatorRegistration(data) {
36
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.RegisterValidator);
37
+ }
38
+ static isValidatorResignation(data) {
39
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.ResignValidator);
40
+ }
41
+ static isUpdateValidator(data) {
42
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.UpdateValidator);
43
+ }
44
+ static isTokenTransfer(data) {
45
+ try {
46
+ const decodedData = new AbiDecoder(ContractAbiType.TOKEN).decodeFunctionData(data);
47
+ return decodedData.functionName === "transfer";
48
+ }
49
+ catch (_a) {
50
+ // Different abi type. Ignore.
51
+ }
52
+ return false;
53
+ }
54
+ }
@@ -6,4 +6,6 @@ export * from "./Message";
6
6
  export * from "./Slot";
7
7
  export * from "./TransactionUtils";
8
8
  export * from "./UnitConverter";
9
+ export * from "./TransactionDataEncoder";
10
+ export * from "./TransactionTypeIdentifier";
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC"}
@@ -6,3 +6,5 @@ export * from "./Message";
6
6
  export * from "./Slot";
7
7
  export * from "./TransactionUtils";
8
8
  export * from "./UnitConverter";
9
+ export * from "./TransactionDataEncoder";
10
+ export * from "./TransactionTypeIdentifier";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkecosystem/typescript-crypto",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "engines": {
5
5
  "node": ">=20.12.2"
6
6
  },
@@ -3,7 +3,9 @@ export enum AbiFunction {
3
3
  UNVOTE = "unvote",
4
4
  VALIDATOR_REGISTRATION = "registerValidator",
5
5
  VALIDATOR_RESIGNATION = "resignValidator",
6
+ UPDATE_VALIDATOR = "updateValidator",
6
7
  USERNAME_REGISTRATION = "registerUsername",
7
8
  USERNAME_RESIGNATION = "resignUsername",
8
9
  MULTIPAYMENT = "pay",
10
+ TRANSFER = "transfer",
9
11
  }
@@ -0,0 +1,35 @@
1
+ import { ITokenTransferBuilder, ITransaction, TransactionData } from "@/types";
2
+
3
+ import { AbstractTransactionBuilder } from "./AbstractTransactionBuilder";
4
+ import { EvmCall } from "@/transactions/types/EvmCall";
5
+ import { Helpers } from "@/utils/Helpers";
6
+ import { AbiEncoder } from "@/utils";
7
+ import { ContractAbiType } from "@/enums";
8
+
9
+ export class TokenTransferBuilder
10
+ extends AbstractTransactionBuilder<ITokenTransferBuilder>
11
+ implements ITokenTransferBuilder
12
+ {
13
+ public constructor(data?: Record<string, unknown>) {
14
+ super(data);
15
+ }
16
+
17
+ public static new(data?: Record<string, unknown>): TokenTransferBuilder {
18
+ return new this(data);
19
+ }
20
+
21
+ public contractAddress(address: string): TokenTransferBuilder {
22
+ this.transaction.data.to = address;
23
+ return this;
24
+ }
25
+
26
+ public recipient(address: string, amount: bigint): TokenTransferBuilder {
27
+ const payload = new AbiEncoder(ContractAbiType.TOKEN).encodeFunctionCall("transfer", [address, amount]);
28
+ this.transaction.data["data"] = Helpers.removeLeadingHexZero(payload);
29
+ return this;
30
+ }
31
+
32
+ protected getTransactionInstance(data?: Record<string, unknown>): ITransaction {
33
+ return new EvmCall(data as TransactionData);
34
+ }
35
+ }
@@ -1,5 +1,6 @@
1
1
  export * from "./AbstractTransactionBuilder";
2
2
  export * from "./EvmCallBuilder";
3
+ export * from "./TokenTransferBuilder";
3
4
  export * from "./MultipaymentBuilder";
4
5
  export * from "./TransferBuilder";
5
6
  export * from "./UnvoteBuilder";
package/src/types.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import BigNumber from "bignumber.js";
2
2
  import { Result } from "ethers";
3
3
 
4
+ export type Hex = `0x${string}`;
5
+
4
6
  export interface TransactionData {
5
7
  gasPrice?: string | null;
6
8
  gasLimit?: string | null;
@@ -81,6 +83,11 @@ export interface IEvmCallBuilder extends ITransactionBuilder<IEvmCallBuilder> {
81
83
  payload(payload: string): IEvmCallBuilder;
82
84
  }
83
85
 
86
+ export interface ITokenTransferBuilder extends ITransactionBuilder<ITokenTransferBuilder> {
87
+ recipient(address: string, amount: bigint): ITokenTransferBuilder;
88
+ contractAddress(address: string): ITokenTransferBuilder;
89
+ }
90
+
84
91
  export interface IMultipaymentBuilder extends ITransactionBuilder<IMultipaymentBuilder> {
85
92
  pay(address: string, amount: string | BigNumber): IMultipaymentBuilder;
86
93
  }
@@ -1,3 +1,4 @@
1
+ import { Hex } from "@/types";
1
2
  import { AbiBase } from "./AbiBase";
2
3
  import { Helpers } from "./Helpers";
3
4
 
@@ -5,4 +6,8 @@ export class AbiEncoder extends AbiBase {
5
6
  encodeFunctionCall(functionName: string, parameters: unknown[]): string {
6
7
  return Helpers.removeLeadingHexZero(this.interface.encodeFunctionData(functionName, parameters));
7
8
  }
9
+
10
+ encodeFunctionCallHex(functionName: string, parameters: unknown[]): Hex {
11
+ return this.interface.encodeFunctionData(functionName, parameters) as Hex;
12
+ }
8
13
  }
@@ -1,4 +1,5 @@
1
1
  import { InvalidUsernameException } from "@/exceptions/InvalidUsernameException";
2
+ import { Hex } from "@/types";
2
3
 
3
4
  export class Helpers {
4
5
  /**
@@ -43,4 +44,18 @@ export class Helpers {
43
44
  public static removeLeadingHexZero(hex: string): string {
44
45
  return hex.replace(/^0x/, ""); // Using replace to only remove the prefix, not leading zeros
45
46
  }
47
+
48
+ /**
49
+ * Adds the leading '0x' to a string.
50
+ *
51
+ * @param string the input without `0x`
52
+ * @returns the hex output with the leading `0x`
53
+ */
54
+ public static addLeadingHexZero(input: string): Hex {
55
+ if (input.startsWith("0x")) {
56
+ return input as Hex;
57
+ }
58
+
59
+ return `0x${input}`;
60
+ }
46
61
  }
@@ -0,0 +1,54 @@
1
+ import { AbiFunction, ContractAbiType } from "@/enums";
2
+ import { AbiEncoder } from "./AbiEncoder";
3
+ import { Hex } from "@/types";
4
+ import { Helpers } from "./Helpers";
5
+
6
+ export class TransactionDataEncoder {
7
+ public static multiPayment(recipients: string[], amounts: string[]): Hex {
8
+ return new AbiEncoder(ContractAbiType.MULTIPAYMENT).encodeFunctionCallHex(AbiFunction.MULTIPAYMENT, [
9
+ recipients,
10
+ amounts,
11
+ ]);
12
+ }
13
+
14
+ public static updateValidator(validatorPublicKey: string): Hex {
15
+ return new AbiEncoder(ContractAbiType.CONSENSUS).encodeFunctionCallHex(AbiFunction.UPDATE_VALIDATOR, [
16
+ Helpers.addLeadingHexZero(validatorPublicKey),
17
+ ]);
18
+ }
19
+
20
+ public static usernameRegistration(username: string): Hex {
21
+ return new AbiEncoder(ContractAbiType.USERNAMES).encodeFunctionCallHex(AbiFunction.USERNAME_REGISTRATION, [
22
+ username,
23
+ ]);
24
+ }
25
+
26
+ public static usernameResignation(): Hex {
27
+ return new AbiEncoder(ContractAbiType.USERNAMES).encodeFunctionCallHex(AbiFunction.USERNAME_RESIGNATION, []);
28
+ }
29
+
30
+ public static validatorRegistration(validatorPublicKey: string): Hex {
31
+ return new AbiEncoder(ContractAbiType.CONSENSUS).encodeFunctionCallHex(AbiFunction.VALIDATOR_REGISTRATION, [
32
+ Helpers.addLeadingHexZero(validatorPublicKey),
33
+ ]);
34
+ }
35
+
36
+ public static validatorResignation(): Hex {
37
+ return new AbiEncoder(ContractAbiType.CONSENSUS).encodeFunctionCallHex(AbiFunction.VALIDATOR_RESIGNATION, []);
38
+ }
39
+
40
+ public static tokenTransfer(recipientAddress: string, amount: string): Hex {
41
+ return new AbiEncoder(ContractAbiType.TOKEN).encodeFunctionCallHex(AbiFunction.TRANSFER, [
42
+ recipientAddress,
43
+ amount,
44
+ ]);
45
+ }
46
+
47
+ public static vote(voteAddress: string): Hex {
48
+ return new AbiEncoder(ContractAbiType.CONSENSUS).encodeFunctionCallHex(AbiFunction.VOTE, [voteAddress]);
49
+ }
50
+
51
+ public static unvote(): Hex {
52
+ return new AbiEncoder(ContractAbiType.CONSENSUS).encodeFunctionCallHex(AbiFunction.UNVOTE, []);
53
+ }
54
+ }
@@ -0,0 +1,65 @@
1
+ import { ContractAbiType } from "@/enums";
2
+ import { AbiDecoder } from "./AbiDecoder";
3
+ import { ConsensusContract, MultipaymentContract, UsernamesContract } from "./Abi/json";
4
+ import { Helpers } from "./Helpers";
5
+
6
+ export const TransactionFunctionSigs = {
7
+ MultiPayment: MultipaymentContract.methodIdentifiers["pay(address[],uint256[])"],
8
+ RegisterUsername: UsernamesContract.methodIdentifiers["registerUsername(string)"],
9
+ ResignUsername: UsernamesContract.methodIdentifiers["resignUsername()"],
10
+ Transfer: "",
11
+ RegisterValidator: ConsensusContract.methodIdentifiers["registerValidator(bytes)"],
12
+ ResignValidator: ConsensusContract.methodIdentifiers["resignValidator()"],
13
+ Vote: ConsensusContract.methodIdentifiers["vote(address)"],
14
+ Unvote: ConsensusContract.methodIdentifiers["unvote()"],
15
+ UpdateValidator: ConsensusContract.methodIdentifiers["updateValidator(bytes)"],
16
+ };
17
+
18
+ export class TransactionTypeIdentifier {
19
+ public static isTransfer(data: string): boolean {
20
+ return data === TransactionFunctionSigs.Transfer;
21
+ }
22
+
23
+ public static isVote(data: string): boolean {
24
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.Vote);
25
+ }
26
+
27
+ public static isUnvote(data: string): boolean {
28
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.Unvote);
29
+ }
30
+
31
+ public static isMultiPayment(data: string): boolean {
32
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.MultiPayment);
33
+ }
34
+
35
+ public static isUsernameRegistration(data: string): boolean {
36
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.RegisterUsername);
37
+ }
38
+
39
+ public static isUsernameResignation(data: string): boolean {
40
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.ResignUsername);
41
+ }
42
+
43
+ public static isValidatorRegistration(data: string): boolean {
44
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.RegisterValidator);
45
+ }
46
+
47
+ public static isValidatorResignation(data: string): boolean {
48
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.ResignValidator);
49
+ }
50
+
51
+ public static isUpdateValidator(data: string): boolean {
52
+ return Helpers.removeLeadingHexZero(data).startsWith(TransactionFunctionSigs.UpdateValidator);
53
+ }
54
+
55
+ public static isTokenTransfer(data: string): boolean {
56
+ try {
57
+ const decodedData = new AbiDecoder(ContractAbiType.TOKEN).decodeFunctionData(data);
58
+ return decodedData.functionName === "transfer";
59
+ } catch {
60
+ // Different abi type. Ignore.
61
+ }
62
+
63
+ return false;
64
+ }
65
+ }
@@ -6,3 +6,5 @@ export * from "./Message";
6
6
  export * from "./Slot";
7
7
  export * from "./TransactionUtils";
8
8
  export * from "./UnitConverter";
9
+ export * from "./TransactionDataEncoder";
10
+ export * from "./TransactionTypeIdentifier";
@@ -0,0 +1,16 @@
1
+ {
2
+ "data": {
3
+ "value": "0",
4
+ "senderPublicKey": "0243333347c8cbf4e3cbc7a96964181d02a2b0c854faa2fef86b4b8d92afcf473d",
5
+ "gasPrice": "5000000000",
6
+ "gasLimit": "21000",
7
+ "nonce": "1",
8
+ "data": "a9059cbb0000000000000000000000006f0182a0cc707b055322ccf6d4cb6a5aff1aeb220000000000000000000000000000000000000000000000000000000000000000",
9
+ "to": "0x6F0182a0cc707b055322CcF6d4CB6a5Aff1aEb22",
10
+ "v": 0,
11
+ "r": "ca5516c582647a1626bfeb4ccf62314dae02c8c561dbff690bdbda89d181e6f7",
12
+ "s": "1b4ddf55e432e532c8e8d1a854f21e0c80e35a35fe4557899fb3f485d071f1e1",
13
+ "hash": "4bb567e6ffd6716b99865fc6917eadf0f5b6cbccdd6999a592db6143a7f24d81"
14
+ },
15
+ "serialized": "f8ab0185012a05f200825208946f0182a0cc707b055322ccf6d4cb6a5aff1aeb2280b844a9059cbb0000000000000000000000006f0182a0cc707b055322ccf6d4cb6a5aff1aeb220000000000000000000000000000000000000000000000000000000000000000825c6ba0ca5516c582647a1626bfeb4ccf62314dae02c8c561dbff690bdbda89d181e6f7a01b4ddf55e432e532c8e8d1a854f21e0c80e35a35fe4557899fb3f485d071f1e1"
16
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "Username": "test",
3
+ "Address": "0xA5cc0BfEB09742C5e4C610f2EBaaB82Eb142Ca10",
4
+ "ValidatorPublicKey": "b209f4a7454ae17c5808991dffbf204c747b851f351d2ce72a6e18903d0e2f609e0328ebbc3fb97cd4d3660b4bc156f1",
5
+ "Amount": "1000000000000",
6
+ "Encoded": {
7
+ "UpdateValidator": "0x5a8eed7300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030b209f4a7454ae17c5808991dffbf204c747b851f351d2ce72a6e18903d0e2f609e0328ebbc3fb97cd4d3660b4bc156f100000000000000000000000000000000",
8
+ "UsernameRegistration": "0x36a94134000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000",
9
+ "UsernameResignation": "0xebed6dab",
10
+ "ValidatorRegistration": "0x602a9eee00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030b209f4a7454ae17c5808991dffbf204c747b851f351d2ce72a6e18903d0e2f609e0328ebbc3fb97cd4d3660b4bc156f100000000000000000000000000000000",
11
+ "ValidatorResignation": "0xb85f5da2",
12
+ "TokenTransfer": "0xa9059cbb000000000000000000000000a5cc0bfeb09742c5e4c610f2ebaab82eb142ca10000000000000000000000000000000000000000000000000000000e8d4a51000",
13
+ "MultiPayment": "0x084ce708000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc0bfeb09742c5e4c610f2ebaab82eb142ca10000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000003e8"
14
+ }
15
+ }
@@ -0,0 +1,138 @@
1
+ import { TokenTransferBuilder } from "@/transactions/builders/TokenTransferBuilder";
2
+ import identityFixture from "@tests/fixtures/identity.json";
3
+ import fixture from "@tests/fixtures/transactions/token-transfer.json";
4
+
5
+ it("should build a token transfer", async () => {
6
+ const transaction = (
7
+ await TokenTransferBuilder.new()
8
+ .recipient(fixture.data.to, BigInt(fixture.data.value))
9
+ .to(fixture.data.to)
10
+ .nonce(fixture.data.nonce)
11
+ .gasPrice(fixture.data.gasPrice)
12
+ .gasLimit(fixture.data.gasLimit)
13
+ .sign(identityFixture.passphrase)
14
+ ).transaction;
15
+
16
+ expect(transaction.data.gasPrice).toBe(fixture.data.gasPrice);
17
+ expect(transaction.data.nonce).toBe(fixture.data.nonce);
18
+ expect(transaction.data.gasLimit).toBe(fixture.data.gasLimit);
19
+ expect(transaction.data.value).toBe("0");
20
+ expect(transaction.data.v).toBe(fixture.data.v);
21
+ expect(transaction.data.r).toBe(fixture.data.r);
22
+ expect(transaction.data.s).toBe(fixture.data.s);
23
+ expect(transaction.data.hash).toBe(fixture.data.hash);
24
+
25
+ expect(transaction.serialize().toString("hex")).toEqual(fixture.serialized);
26
+ expect(transaction.verify()).toBe(true);
27
+ });
28
+
29
+ it("should sign a token transfer", async () => {
30
+ const { transaction } = await TokenTransferBuilder.new()
31
+ .recipient(fixture.data.to, BigInt(fixture.data.value))
32
+ .to(fixture.data.to)
33
+ .nonce(fixture.data.nonce)
34
+ .gasPrice(fixture.data.gasPrice)
35
+ .gasLimit(fixture.data.gasLimit)
36
+ .sign(identityFixture.passphrase);
37
+
38
+ expect(transaction.data.gasPrice).toBe(fixture.data.gasPrice);
39
+ expect(transaction.data.nonce).toBe(fixture.data.nonce);
40
+ expect(transaction.data.gasLimit).toBe(fixture.data.gasLimit);
41
+ expect(transaction.data.to).toBe(fixture.data.to);
42
+ expect(transaction.data.value).toBe(fixture.data.value);
43
+ expect(transaction.data.v).toBe(fixture.data.v);
44
+ expect(transaction.data.r).toBe(fixture.data.r);
45
+ expect(transaction.data.s).toBe(fixture.data.s);
46
+ expect(transaction.data.hash).toBe(fixture.data.hash);
47
+
48
+ expect(transaction.serialize().toString("hex")).toEqual(fixture.serialized);
49
+ expect(transaction.verify()).toBe(true);
50
+ });
51
+
52
+ it("should verify", async () => {
53
+ const transaction = await TokenTransferBuilder.new()
54
+ .recipient(fixture.data.to, BigInt(fixture.data.value))
55
+ .to(fixture.data.to)
56
+ .nonce(fixture.data.nonce)
57
+ .gasPrice(fixture.data.gasPrice)
58
+ .gasLimit(fixture.data.gasLimit)
59
+ .sign(identityFixture.passphrase);
60
+
61
+ expect(transaction.verify()).toBe(true);
62
+ });
63
+
64
+ it("should convert to an array", async () => {
65
+ const transaction = await TokenTransferBuilder.new()
66
+ .recipient(fixture.data.to, BigInt(fixture.data.value))
67
+ .to(fixture.data.to)
68
+ .nonce(fixture.data.nonce)
69
+ .gasPrice(fixture.data.gasPrice)
70
+ .gasLimit(fixture.data.gasLimit)
71
+ .sign(identityFixture.passphrase);
72
+
73
+ expect(transaction.toObject()).toEqual({
74
+ data: fixture.data.data,
75
+ to: fixture.data.to,
76
+ value: fixture.data.value,
77
+ gasPrice: fixture.data.gasPrice,
78
+ gasLimit: fixture.data.gasLimit,
79
+ nonce: fixture.data.nonce,
80
+ v: fixture.data.v,
81
+ r: fixture.data.r,
82
+ s: fixture.data.s,
83
+ senderPublicKey: fixture.data.senderPublicKey,
84
+ hash: fixture.data.hash,
85
+ });
86
+ });
87
+
88
+ it("should convert to json", async () => {
89
+ const transaction = await TokenTransferBuilder.new()
90
+ .recipient(fixture.data.to, BigInt(fixture.data.value))
91
+ .to(fixture.data.to)
92
+ .nonce(fixture.data.nonce)
93
+ .gasPrice(fixture.data.gasPrice)
94
+ .gasLimit(fixture.data.gasLimit)
95
+ .sign(identityFixture.passphrase);
96
+
97
+ expect(transaction.toJson()).toEqual(
98
+ JSON.stringify({
99
+ gasPrice: fixture.data.gasPrice,
100
+ hash: fixture.data.hash,
101
+ gasLimit: fixture.data.gasLimit,
102
+ nonce: fixture.data.nonce,
103
+ senderPublicKey: fixture.data.senderPublicKey,
104
+ to: fixture.data.to,
105
+ value: fixture.data.value,
106
+ data: fixture.data.data,
107
+ r: fixture.data.r,
108
+ s: fixture.data.s,
109
+ v: fixture.data.v,
110
+ }),
111
+ );
112
+ });
113
+
114
+ it("should convert to string", async () => {
115
+ const transaction = await TokenTransferBuilder.new()
116
+ .recipient(fixture.data.to, BigInt(fixture.data.value))
117
+ .to(fixture.data.to)
118
+ .nonce(fixture.data.nonce)
119
+ .gasPrice(fixture.data.gasPrice)
120
+ .gasLimit(fixture.data.gasLimit)
121
+ .sign(identityFixture.passphrase);
122
+
123
+ expect(transaction.toString()).toEqual(
124
+ JSON.stringify({
125
+ gasPrice: fixture.data.gasPrice,
126
+ hash: fixture.data.hash,
127
+ gasLimit: fixture.data.gasLimit,
128
+ nonce: fixture.data.nonce,
129
+ senderPublicKey: fixture.data.senderPublicKey,
130
+ to: fixture.data.to,
131
+ value: fixture.data.value,
132
+ data: fixture.data.data,
133
+ r: fixture.data.r,
134
+ s: fixture.data.s,
135
+ v: fixture.data.v,
136
+ }),
137
+ );
138
+ });
@@ -46,3 +46,15 @@ it("should encode using a custom abi", () => {
46
46
 
47
47
  expect(encodedData).toBe(expectedEncodedData);
48
48
  });
49
+
50
+ it("should encode a vote function call to hex", () => {
51
+ const encoder = new AbiEncoder();
52
+
53
+ const functionName = "vote";
54
+ const args = ["0x512F366D524157BcF734546eB29a6d687B762255"];
55
+ const expectedEncodedData = "6dd7d8ea000000000000000000000000512f366d524157bcf734546eb29a6d687b762255";
56
+
57
+ const encodedData = encoder.encodeFunctionCallHex(functionName, args);
58
+
59
+ expect(encodedData).toBe(`0x${expectedEncodedData}`);
60
+ });
@@ -117,4 +117,14 @@ describe("Helpers", () => {
117
117
  expect(Helpers.removeLeadingHexZero("0X1234")).toBe("0X1234"); // case sensitive
118
118
  });
119
119
  });
120
+
121
+ describe("addLeadingHexZero", () => {
122
+ it("should add the 0x prefix to string", () => {
123
+ expect(Helpers.addLeadingHexZero("1234")).toBe("0x1234");
124
+ });
125
+
126
+ it("should not add the 0x prefix to string if it has already", () => {
127
+ expect(Helpers.addLeadingHexZero("0x1234")).toBe("0x1234");
128
+ });
129
+ });
120
130
  });
@@ -0,0 +1,51 @@
1
+ import { TransactionDataEncoder } from "@/utils/TransactionDataEncoder";
2
+ import EncoderFixture from "@tests/fixtures/transactions/transaction-data-encoder.json";
3
+
4
+ it("should encode multi payment", () => {
5
+ const encoded = TransactionDataEncoder.multiPayment([EncoderFixture.Address], ["1000"]);
6
+ expect(encoded).toEqual(EncoderFixture.Encoded.MultiPayment);
7
+ });
8
+
9
+ it("should encode update validator", () => {
10
+ const encoded = TransactionDataEncoder.updateValidator(EncoderFixture.ValidatorPublicKey);
11
+ expect(encoded).toEqual(EncoderFixture.Encoded.UpdateValidator);
12
+ });
13
+
14
+ it("should encode username registration", () => {
15
+ const encoded = TransactionDataEncoder.usernameRegistration(EncoderFixture.Username);
16
+ expect(encoded).toEqual(EncoderFixture.Encoded.UsernameRegistration);
17
+ });
18
+
19
+ it("should encode username resignation", () => {
20
+ const encoded = TransactionDataEncoder.usernameResignation();
21
+ expect(encoded).toEqual(EncoderFixture.Encoded.UsernameResignation);
22
+ });
23
+
24
+ it("should encode validator registration", () => {
25
+ const encoded = TransactionDataEncoder.validatorRegistration(EncoderFixture.ValidatorPublicKey);
26
+ expect(encoded).toEqual(EncoderFixture.Encoded.ValidatorRegistration);
27
+ });
28
+
29
+ it("should encode validator resignation", () => {
30
+ const encoded = TransactionDataEncoder.validatorResignation();
31
+ expect(encoded).toEqual(EncoderFixture.Encoded.ValidatorResignation);
32
+ });
33
+
34
+ it("should encode token uransfer", () => {
35
+ const encoded = TransactionDataEncoder.tokenTransfer(EncoderFixture.Address, EncoderFixture.Amount);
36
+ expect(encoded).toEqual(EncoderFixture.Encoded.TokenTransfer);
37
+ });
38
+
39
+ it("should reject invalid address format in tokenTransfer", () => {
40
+ expect(() => TransactionDataEncoder.tokenTransfer("", "1000")).toThrow();
41
+ expect(() => TransactionDataEncoder.tokenTransfer("0x123", "1000")).toThrow();
42
+ expect(() => TransactionDataEncoder.tokenTransfer("0x123456789012345678901234567890123456789", "1000")).toThrow();
43
+ });
44
+
45
+ it("should reject invalid address format in multiPayment", () => {
46
+ expect(() => TransactionDataEncoder.multiPayment([""], ["1000"])).toThrow();
47
+ expect(() => TransactionDataEncoder.multiPayment(["0x123"], ["1000"])).toThrow();
48
+ expect(() =>
49
+ TransactionDataEncoder.multiPayment(["0x123456789012345678901234567890123456789"], ["1000"]),
50
+ ).toThrow();
51
+ });