@aptos-labs/ts-sdk 0.0.0

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 (110) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +144 -0
  3. package/dist/browser/index.global.js +410 -0
  4. package/dist/browser/index.global.js.map +1 -0
  5. package/dist/cjs/index.d.ts +4965 -0
  6. package/dist/cjs/index.js +4762 -0
  7. package/dist/cjs/index.js.map +1 -0
  8. package/dist/esm/index.d.ts +4965 -0
  9. package/dist/esm/index.mjs +4645 -0
  10. package/dist/esm/index.mjs.map +1 -0
  11. package/dist/types/index.d.ts +1247 -0
  12. package/dist/types/index.js +151 -0
  13. package/dist/types/index.js.map +1 -0
  14. package/package.json +79 -0
  15. package/src/api/account.ts +360 -0
  16. package/src/api/aptos.ts +103 -0
  17. package/src/api/aptosConfig.ts +77 -0
  18. package/src/api/coin.ts +39 -0
  19. package/src/api/digitalAsset.ts +192 -0
  20. package/src/api/event.ts +78 -0
  21. package/src/api/faucet.ts +30 -0
  22. package/src/api/fungibleAsset.ts +82 -0
  23. package/src/api/general.ts +188 -0
  24. package/src/api/index.ts +5 -0
  25. package/src/api/staking.ts +58 -0
  26. package/src/api/transaction.ts +135 -0
  27. package/src/api/transactionSubmission.ts +168 -0
  28. package/src/bcs/consts.ts +12 -0
  29. package/src/bcs/deserializer.ts +248 -0
  30. package/src/bcs/index.ts +9 -0
  31. package/src/bcs/serializable/entryFunctionBytes.ts +61 -0
  32. package/src/bcs/serializable/fixedBytes.ts +65 -0
  33. package/src/bcs/serializable/movePrimitives.ts +211 -0
  34. package/src/bcs/serializable/moveStructs.ts +462 -0
  35. package/src/bcs/serializer.ts +353 -0
  36. package/src/client/core.ts +106 -0
  37. package/src/client/get.ts +109 -0
  38. package/src/client/index.ts +7 -0
  39. package/src/client/post.ts +90 -0
  40. package/src/client/types.ts +58 -0
  41. package/src/core/account.ts +180 -0
  42. package/src/core/accountAddress.ts +407 -0
  43. package/src/core/authenticationKey.ts +102 -0
  44. package/src/core/common.ts +40 -0
  45. package/src/core/crypto/asymmetricCrypto.ts +77 -0
  46. package/src/core/crypto/ed25519.ts +224 -0
  47. package/src/core/crypto/index.ts +7 -0
  48. package/src/core/crypto/multiEd25519.ts +251 -0
  49. package/src/core/crypto/secp256k1.ts +227 -0
  50. package/src/core/hex.ts +177 -0
  51. package/src/core/index.ts +9 -0
  52. package/src/index.ts +12 -0
  53. package/src/internal/account.ts +484 -0
  54. package/src/internal/coin.ts +32 -0
  55. package/src/internal/digitalAsset.ts +302 -0
  56. package/src/internal/event.ts +88 -0
  57. package/src/internal/faucet.ts +41 -0
  58. package/src/internal/fungibleAsset.ts +114 -0
  59. package/src/internal/general.ts +160 -0
  60. package/src/internal/queries/TokenActivitiesFieldsFragment.graphql +17 -0
  61. package/src/internal/queries/currentTokenOwnershipFieldsFragment.graphql +45 -0
  62. package/src/internal/queries/getAccountCoinCount.graphql +7 -0
  63. package/src/internal/queries/getAccountCoinsData.graphql +32 -0
  64. package/src/internal/queries/getAccountCollectionsWithOwnedTokens.graphql +33 -0
  65. package/src/internal/queries/getAccountOwnedObjects.graphql +16 -0
  66. package/src/internal/queries/getAccountOwnedTokens.graphql +11 -0
  67. package/src/internal/queries/getAccountOwnedTokensByTokenData.graphql +11 -0
  68. package/src/internal/queries/getAccountOwnedTokensFromCollectionAddress.graphql +11 -0
  69. package/src/internal/queries/getAccountTokensCount.graphql +7 -0
  70. package/src/internal/queries/getAccountTransactionsCount.graphql +7 -0
  71. package/src/internal/queries/getChainTopUserTransactions.graphql +5 -0
  72. package/src/internal/queries/getCollectionData.graphql +20 -0
  73. package/src/internal/queries/getCurrentFungibleAssetBalances.graphql +17 -0
  74. package/src/internal/queries/getDelegatedStakingActivities.graphql +12 -0
  75. package/src/internal/queries/getEvents.graphql +12 -0
  76. package/src/internal/queries/getFungibleAssetActivities.graphql +20 -0
  77. package/src/internal/queries/getFungibleAssetMetadata.graphql +16 -0
  78. package/src/internal/queries/getNumberOfDelegatorsQuery.graphql +9 -0
  79. package/src/internal/queries/getProcessorStatus.graphql +7 -0
  80. package/src/internal/queries/getTokenActivity.graphql +11 -0
  81. package/src/internal/queries/getTokenCurrentOwner.graphql +11 -0
  82. package/src/internal/queries/getTokenData.graphql +38 -0
  83. package/src/internal/staking.ts +68 -0
  84. package/src/internal/transaction.ts +245 -0
  85. package/src/internal/transactionSubmission.ts +162 -0
  86. package/src/transactions/authenticator/account.ts +121 -0
  87. package/src/transactions/authenticator/transaction.ts +222 -0
  88. package/src/transactions/instances/chainId.ts +26 -0
  89. package/src/transactions/instances/identifier.ts +28 -0
  90. package/src/transactions/instances/index.ts +9 -0
  91. package/src/transactions/instances/moduleId.ts +53 -0
  92. package/src/transactions/instances/rawTransaction.ts +199 -0
  93. package/src/transactions/instances/signedTransaction.ts +43 -0
  94. package/src/transactions/instances/transactionArgument.ts +37 -0
  95. package/src/transactions/instances/transactionPayload.ts +407 -0
  96. package/src/transactions/transaction_builder/transaction_builder.ts +541 -0
  97. package/src/transactions/typeTag/typeTag.ts +487 -0
  98. package/src/transactions/types.ts +262 -0
  99. package/src/types/codegen.yaml +33 -0
  100. package/src/types/generated/operations.ts +623 -0
  101. package/src/types/generated/queries.ts +737 -0
  102. package/src/types/generated/types.ts +10387 -0
  103. package/src/types/index.ts +944 -0
  104. package/src/types/indexer.ts +93 -0
  105. package/src/utils/apiEndpoints.ts +36 -0
  106. package/src/utils/const.ts +51 -0
  107. package/src/utils/hdKey.ts +113 -0
  108. package/src/utils/helpers.ts +12 -0
  109. package/src/utils/memoize.ts +68 -0
  110. package/src/version.ts +9 -0
@@ -0,0 +1,58 @@
1
+ // Copyright © Aptos Foundation
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { AptosRequest } from "../types";
5
+
6
+ /**
7
+ * The API response type
8
+ *
9
+ * @param status - the response status. i.e. 200
10
+ * @param statusText - the response message
11
+ * @param data the response data
12
+ * @param url the url the request was made to
13
+ * @param headers the response headers
14
+ * @param config (optional) - the request object
15
+ * @param request (optional) - the request object
16
+ */
17
+ export interface AptosResponse<Req, Res> {
18
+ status: number;
19
+ statusText: string;
20
+ data: Res;
21
+ url: string;
22
+ headers: any;
23
+ config?: any;
24
+ request?: Req;
25
+ }
26
+
27
+ /**
28
+ * The type returned from an API error
29
+ *
30
+ * @param name - the error name "AptosApiError"
31
+ * @param url the url the request was made to
32
+ * @param status - the response status. i.e. 400
33
+ * @param statusText - the response message
34
+ * @param data the response data
35
+ * @param request - the AptosRequest
36
+ */
37
+ export class AptosApiError extends Error {
38
+ readonly url: string;
39
+
40
+ readonly status: number;
41
+
42
+ readonly statusText: string;
43
+
44
+ readonly data: any;
45
+
46
+ readonly request: AptosRequest;
47
+
48
+ constructor(request: AptosRequest, response: AptosResponse<any, any>, message: string) {
49
+ super(message);
50
+
51
+ this.name = "AptosApiError";
52
+ this.url = response.url;
53
+ this.status = response.status;
54
+ this.statusText = response.statusText;
55
+ this.data = response.data;
56
+ this.request = request;
57
+ }
58
+ }
@@ -0,0 +1,180 @@
1
+ // Copyright © Aptos Foundation
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { AccountAddress } from "./accountAddress";
5
+ import { AuthenticationKey } from "./authenticationKey";
6
+ import { PrivateKey, PublicKey, Signature } from "./crypto/asymmetricCrypto";
7
+ import { Ed25519PrivateKey, Ed25519PublicKey } from "./crypto/ed25519";
8
+ import { MultiEd25519PublicKey } from "./crypto/multiEd25519";
9
+ import { Secp256k1PrivateKey, Secp256k1PublicKey } from "./crypto/secp256k1";
10
+ import { Hex } from "./hex";
11
+ import { HexInput, SigningScheme } from "../types";
12
+ import { derivePrivateKeyFromMnemonic, KeyType } from "../utils/hdKey";
13
+
14
+ /**
15
+ * Class for creating and managing account on Aptos network
16
+ *
17
+ * Use this class to create accounts, sign transactions, and more.
18
+ * Note: Creating an account instance does not create the account on-chain.
19
+ */
20
+ export class Account {
21
+ /**
22
+ * Public key associated with the account
23
+ */
24
+ readonly publicKey: PublicKey;
25
+
26
+ /**
27
+ * Private key associated with the account
28
+ */
29
+ readonly privateKey: PrivateKey;
30
+
31
+ /**
32
+ * Account address associated with the account
33
+ */
34
+ readonly accountAddress: AccountAddress;
35
+
36
+ /**
37
+ * Signing scheme used to sign transactions
38
+ */
39
+ readonly signingScheme: SigningScheme;
40
+
41
+ /**
42
+ * constructor for Account
43
+ *
44
+ * Need to update this to use the new crypto library if new schemes are added.
45
+ *
46
+ * @param args.privateKey PrivateKey - private key of the account
47
+ * @param args.address AccountAddress - address of the account
48
+ *
49
+ * This method is private because it should only be called by the factory static methods.
50
+ * @returns Account
51
+ */
52
+ private constructor(args: { privateKey: PrivateKey; address: AccountAddress }) {
53
+ const { privateKey, address } = args;
54
+
55
+ // Derive the public key from the private key
56
+ this.publicKey = privateKey.publicKey();
57
+
58
+ // Derive the signing scheme from the public key
59
+ if (this.publicKey instanceof Ed25519PublicKey) {
60
+ this.signingScheme = SigningScheme.Ed25519;
61
+ } else if (this.publicKey instanceof MultiEd25519PublicKey) {
62
+ this.signingScheme = SigningScheme.MultiEd25519;
63
+ } else if (this.publicKey instanceof Secp256k1PublicKey) {
64
+ this.signingScheme = SigningScheme.Secp256k1Ecdsa;
65
+ } else {
66
+ throw new Error("Can not create new Account, unsupported public key type");
67
+ }
68
+
69
+ this.privateKey = privateKey;
70
+ this.accountAddress = address;
71
+ }
72
+
73
+ /**
74
+ * Derives an account with random private key and address
75
+ *
76
+ * @param scheme optional SigningScheme - type of SigningScheme to use. Default to Ed25519
77
+ * Currently only Ed25519 and Secp256k1 are supported
78
+ *
79
+ * @returns Account with the given signing scheme
80
+ */
81
+ static generate(scheme?: SigningScheme): Account {
82
+ let privateKey: PrivateKey;
83
+
84
+ switch (scheme) {
85
+ case SigningScheme.Secp256k1Ecdsa:
86
+ privateKey = Secp256k1PrivateKey.generate();
87
+ break;
88
+ // TODO: Add support for MultiEd25519
89
+ default:
90
+ privateKey = Ed25519PrivateKey.generate();
91
+ }
92
+
93
+ const address = new AccountAddress({
94
+ data: Account.authKey({
95
+ publicKey: privateKey.publicKey(),
96
+ }).toUint8Array(),
97
+ });
98
+ return new Account({ privateKey, address });
99
+ }
100
+
101
+ /**
102
+ * Derives an account with provided private key
103
+ *
104
+ * @param privateKey Hex - private key of the account
105
+ * @returns Account
106
+ */
107
+ static fromPrivateKey(privateKey: PrivateKey): Account {
108
+ const publicKey = privateKey.publicKey();
109
+ const authKey = Account.authKey({ publicKey });
110
+ const address = new AccountAddress({ data: authKey.toUint8Array() });
111
+ return Account.fromPrivateKeyAndAddress({ privateKey, address });
112
+ }
113
+
114
+ /**
115
+ * Derives an account with provided private key and address
116
+ * This is intended to be used for account that has it's key rotated
117
+ *
118
+ * @param args.privateKey Hex - private key of the account
119
+ * @param args.address AccountAddress - address of the account
120
+ * @returns Account
121
+ */
122
+ static fromPrivateKeyAndAddress(args: { privateKey: PrivateKey; address: AccountAddress }): Account {
123
+ return new Account(args);
124
+ }
125
+
126
+ /**
127
+ * Derives an account with bip44 path and mnemonics,
128
+ *
129
+ * @param args.path the BIP44 derive path (e.g. m/44'/637'/0'/0'/0')
130
+ * Detailed description: {@link https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki}
131
+ * @param args.mnemonic the mnemonic seed phrase of the account
132
+ * @returns AptosAccount
133
+ */
134
+ static fromDerivationPath(args: { path: string; mnemonic: string }): Account {
135
+ const { path, mnemonic } = args;
136
+
137
+ const { key } = derivePrivateKeyFromMnemonic(KeyType.ED25519, path, mnemonic);
138
+ const privateKey = new Ed25519PrivateKey(key);
139
+ return Account.fromPrivateKey(privateKey);
140
+ }
141
+
142
+ /**
143
+ * This key enables account owners to rotate their private key(s)
144
+ * associated with the account without changing the address that hosts their account.
145
+ * See here for more info: {@link https://aptos.dev/concepts/accounts#single-signer-authentication}
146
+ *
147
+ * @param args.publicKey PublicKey - public key of the account
148
+ * @returns Authentication key for the associated account
149
+ */
150
+ static authKey(args: { publicKey: PublicKey }): Hex {
151
+ const { publicKey } = args;
152
+ const authKey = AuthenticationKey.fromPublicKey({ publicKey });
153
+ return authKey.data;
154
+ }
155
+
156
+ /**
157
+ * Sign the given message with the private key.
158
+ *
159
+ * TODO: Add sign transaction or specific types
160
+ *
161
+ * @param data in HexInput format
162
+ * @returns Signature
163
+ */
164
+ sign(data: HexInput): Signature {
165
+ return this.privateKey.sign(data);
166
+ }
167
+
168
+ /**
169
+ * Verify the given message and signature with the public key.
170
+ *
171
+ * @param args.message raw message data in HexInput format
172
+ * @param args.signature signed message Signature
173
+ * @returns
174
+ */
175
+ verifySignature(args: { message: HexInput; signature: Signature }): boolean {
176
+ const { message, signature } = args;
177
+ const rawMessage = Hex.fromHexInput(message).toUint8Array();
178
+ return this.publicKey.verifySignature({ message: rawMessage, signature });
179
+ }
180
+ }
@@ -0,0 +1,407 @@
1
+ // Copyright © Aptos Foundation
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
5
+ import { Serializable, Serializer } from "../bcs/serializer";
6
+ import { Deserializer } from "../bcs/deserializer";
7
+ import { ParsingError, ParsingResult } from "./common";
8
+ import { TransactionArgument } from "../transactions/instances/transactionArgument";
9
+ import { HexInput, ScriptTransactionArgumentVariants } from "../types";
10
+
11
+ /**
12
+ * This enum is used to explain why an address was invalid.
13
+ */
14
+ export enum AddressInvalidReason {
15
+ INCORRECT_NUMBER_OF_BYTES = "incorrect_number_of_bytes",
16
+ INVALID_HEX_CHARS = "invalid_hex_chars",
17
+ TOO_SHORT = "too_short",
18
+ TOO_LONG = "too_long",
19
+ LEADING_ZERO_X_REQUIRED = "leading_zero_x_required",
20
+ LONG_FORM_REQUIRED_UNLESS_SPECIAL = "long_form_required_unless_special",
21
+ INVALID_PADDING_ZEROES = "INVALID_PADDING_ZEROES",
22
+ }
23
+
24
+ /**
25
+ * NOTE: Only use this class for account addresses. For other hex data, e.g. transaction
26
+ * hashes, use the Hex class.
27
+ *
28
+ * AccountAddress is used for working with account addresses. Account addresses, when
29
+ * represented as a string, generally look like these examples:
30
+ * - 0x1
31
+ * - 0xaa86fe99004361f747f91342ca13c426ca0cccb0c1217677180c9493bad6ef0c
32
+ *
33
+ * Proper formatting and parsing of account addresses is defined by AIP-40.
34
+ * To learn more about the standard, read the AIP here:
35
+ * https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-40.md.
36
+ *
37
+ * The comments in this class make frequent reference to the LONG and SHORT formats,
38
+ * as well as "special" addresses. To learn what these refer to see AIP-40.
39
+ */
40
+ export class AccountAddress extends Serializable implements TransactionArgument {
41
+ /**
42
+ * This is the internal representation of an account address.
43
+ */
44
+ readonly data: Uint8Array;
45
+
46
+ /**
47
+ * The number of bytes that make up an account address.
48
+ */
49
+ static readonly LENGTH: number = 32;
50
+
51
+ /**
52
+ * The length of an address string in LONG form without a leading 0x.
53
+ */
54
+ static readonly LONG_STRING_LENGTH: number = 64;
55
+
56
+ static ONE: AccountAddress = AccountAddress.fromString("0x1");
57
+
58
+ static TWO: AccountAddress = AccountAddress.fromString("0x2");
59
+
60
+ static THREE: AccountAddress = AccountAddress.fromString("0x3");
61
+
62
+ static FOUR: AccountAddress = AccountAddress.fromString("0x4");
63
+
64
+ /**
65
+ * Creates an instance of AccountAddress from a Uint8Array.
66
+ *
67
+ * @param args.data A Uint8Array representing an account address.
68
+ */
69
+ constructor(args: { data: Uint8Array }) {
70
+ super();
71
+ if (args.data.length !== AccountAddress.LENGTH) {
72
+ throw new ParsingError(
73
+ "AccountAddress data should be exactly 32 bytes long",
74
+ AddressInvalidReason.INCORRECT_NUMBER_OF_BYTES,
75
+ );
76
+ }
77
+ this.data = args.data;
78
+ }
79
+
80
+ /**
81
+ * Returns whether an address is special, where special is defined as 0x0 to 0xf
82
+ * inclusive. In other words, the last byte of the address must be < 0b10000 (16)
83
+ * and every other byte must be zero.
84
+ *
85
+ * For more information on how special addresses are defined see AIP-40:
86
+ * https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-40.md.
87
+ *
88
+ * @returns true if the address is special, false if not.
89
+ */
90
+ isSpecial(): boolean {
91
+ return (
92
+ this.data.slice(0, this.data.length - 1).every((byte) => byte === 0) && this.data[this.data.length - 1] < 0b10000
93
+ );
94
+ }
95
+
96
+ // ===
97
+ // Methods for representing an instance of AccountAddress as other types.
98
+ // ===
99
+
100
+ /**
101
+ * Return the AccountAddress as a string as per AIP-40.
102
+ * https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-40.md.
103
+ *
104
+ * In short, it means that special addresses are represented in SHORT form, meaning
105
+ * 0x0 through to 0xf inclusive, and every other address is represented in LONG form,
106
+ * meaning 0x + 64 hex characters.
107
+ *
108
+ * @returns AccountAddress as a string conforming to AIP-40.
109
+ */
110
+ toString(): string {
111
+ return `0x${this.toStringWithoutPrefix()}`;
112
+ }
113
+
114
+ /**
115
+ * NOTE: Prefer to use `toString` where possible.
116
+ *
117
+ * Return the AccountAddress as a string as per AIP-40 but without the leading 0x.
118
+ *
119
+ * Learn more by reading the docstring of `toString`.
120
+ *
121
+ * @returns AccountAddress as a string conforming to AIP-40 but without the leading 0x.
122
+ */
123
+ toStringWithoutPrefix(): string {
124
+ let hex = bytesToHex(this.data);
125
+ if (this.isSpecial()) {
126
+ hex = hex[hex.length - 1];
127
+ }
128
+ return hex;
129
+ }
130
+
131
+ /**
132
+ * NOTE: Prefer to use `toString` where possible.
133
+ *
134
+ * Whereas toString will format special addresses (as defined by isSpecial) using the
135
+ * SHORT form (no leading 0s), this format the address in the LONG format
136
+ * unconditionally.
137
+ *
138
+ * This means it will be 0x + 64 hex characters.
139
+ *
140
+ * @returns AccountAddress as a string in LONG form.
141
+ */
142
+ toStringLong(): string {
143
+ return `0x${this.toStringLongWithoutPrefix()}`;
144
+ }
145
+
146
+ /**
147
+ * NOTE: Prefer to use `toString` where possible.
148
+ *
149
+ * Whereas toString will format special addresses (as defined by isSpecial) using the
150
+ * SHORT form (no leading 0s), this function will include leading zeroes. The string
151
+ * will not have a leading zero.
152
+ *
153
+ * This means it will be 64 hex characters without a leading 0x.
154
+ *
155
+ * @returns AccountAddress as a string in LONG form without a leading 0x.
156
+ */
157
+ toStringLongWithoutPrefix(): string {
158
+ return bytesToHex(this.data);
159
+ }
160
+
161
+ /**
162
+ * Get the inner hex data. The inner data is already a Uint8Array so no conversion
163
+ * is taking place here, it just returns the inner data.
164
+ *
165
+ * @returns Hex data as Uint8Array
166
+ */
167
+ toUint8Array(): Uint8Array {
168
+ return this.data;
169
+ }
170
+
171
+ /**
172
+ * Serialize the AccountAddress to a Serializer instance's data buffer.
173
+ * @param serializer The serializer to serialize the AccountAddress to.
174
+ * @returns void
175
+ * @example
176
+ * const serializer = new Serializer();
177
+ * const address = AccountAddress.fromString("0x1");
178
+ * address.serialize(serializer);
179
+ * const bytes = serializer.toUint8Array();
180
+ * // `bytes` is now the BCS-serialized address.
181
+ */
182
+ serialize(serializer: Serializer): void {
183
+ serializer.serializeFixedBytes(this.data);
184
+ }
185
+
186
+ serializeForEntryFunction(serializer: Serializer): void {
187
+ const bcsBytes = this.bcsToBytes();
188
+ serializer.serializeBytes(bcsBytes);
189
+ }
190
+
191
+ serializeForScriptFunction(serializer: Serializer): void {
192
+ serializer.serializeU32AsUleb128(ScriptTransactionArgumentVariants.Address);
193
+ serializer.serialize(this);
194
+ }
195
+
196
+ /**
197
+ * Deserialize an AccountAddress from the byte buffer in a Deserializer instance.
198
+ * @param deserializer The deserializer to deserialize the AccountAddress from.
199
+ * @returns An instance of AccountAddress.
200
+ * @example
201
+ * const bytes = hexToBytes("0x0102030405060708091011121314151617181920212223242526272829303132");
202
+ * const deserializer = new Deserializer(bytes);
203
+ * const address = AccountAddress.deserialize(deserializer);
204
+ * // `address` is now an instance of AccountAddress.
205
+ */
206
+ static deserialize(deserializer: Deserializer): AccountAddress {
207
+ const bytes = deserializer.deserializeFixedBytes(AccountAddress.LENGTH);
208
+ return new AccountAddress({ data: bytes });
209
+ }
210
+
211
+ // ===
212
+ // Methods for creating an instance of AccountAddress from other types.
213
+ // ===
214
+
215
+ /**
216
+ * NOTE: This function has strict parsing behavior. For relaxed behavior, please use
217
+ * the `fromStringRelaxed` function.
218
+ *
219
+ * Creates an instance of AccountAddress from a hex string.
220
+ *
221
+ * This function allows only the strictest formats defined by AIP-40. In short this
222
+ * means only the following formats are accepted:
223
+ *
224
+ * - LONG
225
+ * - SHORT for special addresses
226
+ *
227
+ * Where:
228
+ * - LONG is defined as 0x + 64 hex characters.
229
+ * - SHORT for special addresses is 0x0 to 0xf inclusive without padding zeroes.
230
+ *
231
+ * This means the following are not accepted:
232
+ * - SHORT for non-special addresses.
233
+ * - Any address without a leading 0x.
234
+ *
235
+ * Learn more about the different address formats by reading AIP-40:
236
+ * https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-40.md.
237
+ *
238
+ * @param input A hex string representing an account address.
239
+ *
240
+ * @returns An instance of AccountAddress.
241
+ */
242
+ static fromString(input: string): AccountAddress {
243
+ // Assert the string starts with 0x.
244
+ if (!input.startsWith("0x")) {
245
+ throw new ParsingError("Hex string must start with a leading 0x.", AddressInvalidReason.LEADING_ZERO_X_REQUIRED);
246
+ }
247
+
248
+ const address = AccountAddress.fromStringRelaxed(input);
249
+
250
+ // Check if the address is in LONG form. If it is not, this is only allowed for
251
+ // special addresses, in which case we check it is in proper SHORT form.
252
+ if (input.length !== AccountAddress.LONG_STRING_LENGTH + 2) {
253
+ if (!address.isSpecial()) {
254
+ throw new ParsingError(
255
+ `The given hex string ${address} is not a special address, it must be represented as 0x + 64 chars.`,
256
+ AddressInvalidReason.LONG_FORM_REQUIRED_UNLESS_SPECIAL,
257
+ );
258
+ } else if (input.length !== 3) {
259
+ // 0x + one hex char is the only valid SHORT form for special addresses.
260
+ throw new ParsingError(
261
+ // eslint-disable-next-line max-len
262
+ `The given hex string ${input} is a special address not in LONG form, it must be 0x0 to 0xf without padding zeroes.`,
263
+ AddressInvalidReason.INVALID_PADDING_ZEROES,
264
+ );
265
+ }
266
+ }
267
+
268
+ return address;
269
+ }
270
+
271
+ /**
272
+ * NOTE: This function has relaxed parsing behavior. For strict behavior, please use
273
+ * the `fromString` function. Where possible use `fromString` rather than this
274
+ * function, `fromStringRelaxed` is only provided for backwards compatibility.
275
+ *
276
+ * Creates an instance of AccountAddress from a hex string.
277
+ *
278
+ * This function allows all formats defined by AIP-40. In short this means the
279
+ * following formats are accepted:
280
+ *
281
+ * - LONG, with or without leading 0x
282
+ * - SHORT, with or without leading 0x
283
+ *
284
+ * Where:
285
+ * - LONG is 64 hex characters.
286
+ * - SHORT is 1 to 63 hex characters inclusive.
287
+ * - Padding zeroes are allowed, e.g. 0x0123 is valid.
288
+ *
289
+ * Learn more about the different address formats by reading AIP-40:
290
+ * https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-40.md.
291
+ *
292
+ * @param input A hex string representing an account address.
293
+ *
294
+ * @returns An instance of AccountAddress.
295
+ */
296
+ static fromStringRelaxed(input: string): AccountAddress {
297
+ let parsedInput = input;
298
+ // Remove leading 0x for parsing.
299
+ if (input.startsWith("0x")) {
300
+ parsedInput = input.slice(2);
301
+ }
302
+
303
+ // Ensure the address string is at least 1 character long.
304
+ if (parsedInput.length === 0) {
305
+ throw new ParsingError(
306
+ "Hex string is too short, must be 1 to 64 chars long, excluding the leading 0x.",
307
+ AddressInvalidReason.TOO_SHORT,
308
+ );
309
+ }
310
+
311
+ // Ensure the address string is not longer than 64 characters.
312
+ if (parsedInput.length > 64) {
313
+ throw new ParsingError(
314
+ "Hex string is too long, must be 1 to 64 chars long, excluding the leading 0x.",
315
+ AddressInvalidReason.TOO_LONG,
316
+ );
317
+ }
318
+
319
+ let addressBytes: Uint8Array;
320
+ try {
321
+ // Pad the address with leading zeroes, so it is 64 chars long and then convert
322
+ // the hex string to bytes. Every two characters in a hex string constitutes a
323
+ // single byte. So a 64 length hex string becomes a 32 byte array.
324
+ addressBytes = hexToBytes(parsedInput.padStart(64, "0"));
325
+ } catch (e) {
326
+ const error = e as Error;
327
+ // At this point the only way this can fail is if the hex string contains
328
+ // invalid characters.
329
+ throw new ParsingError(`Hex characters are invalid: ${error.message}`, AddressInvalidReason.INVALID_HEX_CHARS);
330
+ }
331
+
332
+ return new AccountAddress({ data: addressBytes });
333
+ }
334
+
335
+ /**
336
+ * Convenience method for creating an AccountAddress from HexInput. For
337
+ * more information on how this works, see the constructor and fromString.
338
+ *
339
+ * @param input A hex string or Uint8Array representing an account address.
340
+ *
341
+ * @returns An instance of AccountAddress.
342
+ */
343
+ static fromHexInput(input: HexInput): AccountAddress {
344
+ if (input instanceof Uint8Array) {
345
+ return new AccountAddress({ data: input });
346
+ }
347
+ return AccountAddress.fromString(input);
348
+ }
349
+
350
+ /**
351
+ * Convenience method for creating an AccountAddress from HexInput. For
352
+ * more information on how this works, see the constructor and fromStringRelaxed.
353
+ *
354
+ * @param hexInput A hex string or Uint8Array representing an account address.
355
+ *
356
+ * @returns An instance of AccountAddress.
357
+ */
358
+ static fromHexInputRelaxed(hexInput: HexInput): AccountAddress {
359
+ if (hexInput instanceof Uint8Array) {
360
+ return new AccountAddress({ data: hexInput });
361
+ }
362
+ return AccountAddress.fromStringRelaxed(hexInput);
363
+ }
364
+
365
+ // ===
366
+ // Methods for checking validity.
367
+ // ===
368
+
369
+ /**
370
+ * Check if the string is a valid AccountAddress.
371
+ *
372
+ * @param args.input A hex string representing an account address.
373
+ * @param args.relaxed If true, use relaxed parsing behavior. If false, use strict parsing behavior.
374
+ *
375
+ * @returns valid = true if the string is valid, valid = false if not. If the string
376
+ * is not valid, invalidReason will be set explaining why it is invalid.
377
+ */
378
+ static isValid(args: { input: string; relaxed?: boolean }): ParsingResult<AddressInvalidReason> {
379
+ try {
380
+ if (args.relaxed) {
381
+ AccountAddress.fromStringRelaxed(args.input);
382
+ } else {
383
+ AccountAddress.fromString(args.input);
384
+ }
385
+ return { valid: true };
386
+ } catch (e) {
387
+ const error = e as ParsingError<AddressInvalidReason>;
388
+ return {
389
+ valid: false,
390
+ invalidReason: error.invalidReason,
391
+ invalidReasonMessage: error.message,
392
+ };
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Return whether AccountAddresses are equal. AccountAddresses are considered equal
398
+ * if their underlying byte data is identical.
399
+ *
400
+ * @param other The AccountAddress to compare to.
401
+ * @returns true if the AccountAddresses are equal, false if not.
402
+ */
403
+ equals(other: AccountAddress): boolean {
404
+ if (this.data.length !== other.data.length) return false;
405
+ return this.data.every((value, index) => value === other.data[index]);
406
+ }
407
+ }