@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,487 @@
1
+ // Copyright © Aptos Foundation
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ /* eslint-disable @typescript-eslint/no-unused-vars */
5
+ /* eslint-disable class-methods-use-this */
6
+ /* eslint-disable max-classes-per-file */
7
+ import { Deserializer } from "../../bcs/deserializer";
8
+ import { Serializable, Serializer } from "../../bcs/serializer";
9
+ import { AccountAddress } from "../../core";
10
+ import { Identifier } from "../instances/identifier";
11
+ import { TypeTagVariants } from "../../types";
12
+
13
+ export abstract class TypeTag extends Serializable {
14
+ abstract serialize(serializer: Serializer): void;
15
+
16
+ static deserialize(deserializer: Deserializer): TypeTag {
17
+ const index = deserializer.deserializeUleb128AsU32();
18
+ switch (index) {
19
+ case TypeTagVariants.Bool:
20
+ return TypeTagBool.load(deserializer);
21
+ case TypeTagVariants.U8:
22
+ return TypeTagU8.load(deserializer);
23
+ case TypeTagVariants.U64:
24
+ return TypeTagU64.load(deserializer);
25
+ case TypeTagVariants.U128:
26
+ return TypeTagU128.load(deserializer);
27
+ case TypeTagVariants.Address:
28
+ return TypeTagAddress.load(deserializer);
29
+ case TypeTagVariants.Signer:
30
+ return TypeTagSigner.load(deserializer);
31
+ case TypeTagVariants.Vector:
32
+ return TypeTagVector.load(deserializer);
33
+ case TypeTagVariants.Struct:
34
+ return TypeTagStruct.load(deserializer);
35
+ case TypeTagVariants.U16:
36
+ return TypeTagU16.load(deserializer);
37
+ case TypeTagVariants.U32:
38
+ return TypeTagU32.load(deserializer);
39
+ case TypeTagVariants.U256:
40
+ return TypeTagU256.load(deserializer);
41
+ default:
42
+ throw new Error(`Unknown variant index for TypeTag: ${index}`);
43
+ }
44
+ }
45
+ }
46
+
47
+ export class TypeTagBool extends TypeTag {
48
+ serialize(serializer: Serializer): void {
49
+ serializer.serializeU32AsUleb128(TypeTagVariants.Bool);
50
+ }
51
+
52
+ static load(_deserializer: Deserializer): TypeTagBool {
53
+ return new TypeTagBool();
54
+ }
55
+ }
56
+
57
+ export class TypeTagU8 extends TypeTag {
58
+ serialize(serializer: Serializer): void {
59
+ serializer.serializeU32AsUleb128(TypeTagVariants.U8);
60
+ }
61
+
62
+ static load(_deserializer: Deserializer): TypeTagU8 {
63
+ return new TypeTagU8();
64
+ }
65
+ }
66
+
67
+ export class TypeTagU16 extends TypeTag {
68
+ serialize(serializer: Serializer): void {
69
+ serializer.serializeU32AsUleb128(TypeTagVariants.U16);
70
+ }
71
+
72
+ static load(_deserializer: Deserializer): TypeTagU16 {
73
+ return new TypeTagU16();
74
+ }
75
+ }
76
+
77
+ export class TypeTagU32 extends TypeTag {
78
+ serialize(serializer: Serializer): void {
79
+ serializer.serializeU32AsUleb128(TypeTagVariants.U32);
80
+ }
81
+
82
+ static load(_deserializer: Deserializer): TypeTagU32 {
83
+ return new TypeTagU32();
84
+ }
85
+ }
86
+
87
+ export class TypeTagU64 extends TypeTag {
88
+ serialize(serializer: Serializer): void {
89
+ serializer.serializeU32AsUleb128(TypeTagVariants.U64);
90
+ }
91
+
92
+ static load(_deserializer: Deserializer): TypeTagU64 {
93
+ return new TypeTagU64();
94
+ }
95
+ }
96
+
97
+ export class TypeTagU128 extends TypeTag {
98
+ serialize(serializer: Serializer): void {
99
+ serializer.serializeU32AsUleb128(TypeTagVariants.U128);
100
+ }
101
+
102
+ static load(_deserializer: Deserializer): TypeTagU128 {
103
+ return new TypeTagU128();
104
+ }
105
+ }
106
+
107
+ export class TypeTagU256 extends TypeTag {
108
+ serialize(serializer: Serializer): void {
109
+ serializer.serializeU32AsUleb128(TypeTagVariants.U256);
110
+ }
111
+
112
+ static load(_deserializer: Deserializer): TypeTagU256 {
113
+ return new TypeTagU256();
114
+ }
115
+ }
116
+
117
+ export class TypeTagAddress extends TypeTag {
118
+ serialize(serializer: Serializer): void {
119
+ serializer.serializeU32AsUleb128(TypeTagVariants.Address);
120
+ }
121
+
122
+ static load(_deserializer: Deserializer): TypeTagAddress {
123
+ return new TypeTagAddress();
124
+ }
125
+ }
126
+
127
+ export class TypeTagSigner extends TypeTag {
128
+ serialize(serializer: Serializer): void {
129
+ serializer.serializeU32AsUleb128(TypeTagVariants.Signer);
130
+ }
131
+
132
+ static load(_deserializer: Deserializer): TypeTagSigner {
133
+ return new TypeTagSigner();
134
+ }
135
+ }
136
+
137
+ export class TypeTagVector extends TypeTag {
138
+ constructor(public readonly value: TypeTag) {
139
+ super();
140
+ }
141
+
142
+ serialize(serializer: Serializer): void {
143
+ serializer.serializeU32AsUleb128(TypeTagVariants.Vector);
144
+ this.value.serialize(serializer);
145
+ }
146
+
147
+ static load(deserializer: Deserializer): TypeTagVector {
148
+ const value = TypeTag.deserialize(deserializer);
149
+ return new TypeTagVector(value);
150
+ }
151
+ }
152
+
153
+ export class TypeTagStruct extends TypeTag {
154
+ constructor(public readonly value: StructTag) {
155
+ super();
156
+ }
157
+
158
+ serialize(serializer: Serializer): void {
159
+ serializer.serializeU32AsUleb128(TypeTagVariants.Struct);
160
+ this.value.serialize(serializer);
161
+ }
162
+
163
+ static load(deserializer: Deserializer): TypeTagStruct {
164
+ const value = StructTag.deserialize(deserializer);
165
+ return new TypeTagStruct(value);
166
+ }
167
+
168
+ /**
169
+ * This function checks if the TypeTagStruct is a Move String TypeTag.
170
+ * In Move, a string is represented as the String struct from string.move, deployed at `0x1`,
171
+ * meaning it has the following properties:
172
+ * - address: 0x1
173
+ * - module_name: "string"
174
+ * - name: "String"
175
+ *
176
+ * @returns true if the StructTag is a String type tag, false otherwise
177
+ */
178
+ isStringTypeTag(): boolean {
179
+ return (
180
+ this.value.module_name.identifier === "string" &&
181
+ this.value.name.identifier === "String" &&
182
+ this.value.address.toString() === AccountAddress.ONE.toString()
183
+ );
184
+ }
185
+ }
186
+
187
+ export class StructTag extends Serializable {
188
+ public readonly address: AccountAddress;
189
+
190
+ public readonly module_name: Identifier;
191
+
192
+ public readonly name: Identifier;
193
+
194
+ public readonly type_args: Array<TypeTag>;
195
+
196
+ constructor(address: AccountAddress, module_name: Identifier, name: Identifier, type_args: Array<TypeTag>) {
197
+ super();
198
+ this.address = address;
199
+ this.module_name = module_name;
200
+ this.name = name;
201
+ this.type_args = type_args;
202
+ }
203
+
204
+ /**
205
+ * Converts a string literal to a StructTag
206
+ * @param structTag String literal in format "AccountAddress::module_name::ResourceName",
207
+ * e.g. "0x1::aptos_coin::AptosCoin"
208
+ * @returns
209
+ */
210
+ static fromString(structTag: string): StructTag {
211
+ // Use the TypeTagParser to parse the string literal into a TypeTagStruct
212
+ const typeTagStruct = new TypeTagParser(structTag).parseTypeTag() as TypeTagStruct;
213
+
214
+ // Convert and return as a StructTag
215
+ return new StructTag(
216
+ typeTagStruct.value.address,
217
+ typeTagStruct.value.module_name,
218
+ typeTagStruct.value.name,
219
+ typeTagStruct.value.type_args,
220
+ );
221
+ }
222
+
223
+ serialize(serializer: Serializer): void {
224
+ serializer.serialize(this.address);
225
+ serializer.serialize(this.module_name);
226
+ serializer.serialize(this.name);
227
+ serializer.serializeVector(this.type_args);
228
+ }
229
+
230
+ static deserialize(deserializer: Deserializer): StructTag {
231
+ const address = AccountAddress.deserialize(deserializer);
232
+ const moduleName = Identifier.deserialize(deserializer);
233
+ const name = Identifier.deserialize(deserializer);
234
+ const typeArgs = deserializer.deserializeVector(TypeTag);
235
+ return new StructTag(address, moduleName, name, typeArgs);
236
+ }
237
+ }
238
+
239
+ export const stringStructTag = () =>
240
+ new StructTag(AccountAddress.ONE, new Identifier("string"), new Identifier("String"), []);
241
+
242
+ export function optionStructTag(typeArg: TypeTag): StructTag {
243
+ return new StructTag(AccountAddress.ONE, new Identifier("option"), new Identifier("Option"), [typeArg]);
244
+ }
245
+
246
+ export function objectStructTag(typeArg: TypeTag): StructTag {
247
+ return new StructTag(AccountAddress.ONE, new Identifier("object"), new Identifier("Object"), [typeArg]);
248
+ }
249
+
250
+ /**
251
+ * Parser to parse a type tag string
252
+ */
253
+ export class TypeTagParser {
254
+ private readonly tokens: Token[];
255
+
256
+ private readonly typeTags: string[] = [];
257
+
258
+ constructor(tagStr: string, typeTags?: string[]) {
259
+ this.tokens = tokenize(tagStr);
260
+ this.typeTags = typeTags || [];
261
+ }
262
+
263
+ private consume(targetToken: string) {
264
+ const token = this.tokens.shift();
265
+ if (!token || token[1] !== targetToken) {
266
+ bail("Invalid type tag.");
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Consumes all of an unused generic field, mostly applicable to object
272
+ *
273
+ * Note: This is recursive. it can be problematic if there's bad input
274
+ * @private
275
+ */
276
+ private consumeWholeGeneric() {
277
+ this.consume("<");
278
+ while (this.tokens[0][1] !== ">") {
279
+ // If it is nested, we have to consume another nested generic
280
+ if (this.tokens[0][1] === "<") {
281
+ this.consumeWholeGeneric();
282
+ } else {
283
+ this.tokens.shift();
284
+ }
285
+ }
286
+ this.consume(">");
287
+ }
288
+
289
+ private parseCommaList(endToken: string, allowTrailingComma: boolean): TypeTag[] {
290
+ const res: TypeTag[] = [];
291
+ if (this.tokens.length <= 0) {
292
+ bail("Invalid type tag.");
293
+ }
294
+
295
+ while (this.tokens[0][1] !== endToken) {
296
+ res.push(this.parseTypeTag());
297
+
298
+ if (this.tokens.length > 0 && this.tokens[0][1] === endToken) {
299
+ break;
300
+ }
301
+
302
+ this.consume(",");
303
+ if (this.tokens.length > 0 && this.tokens[0][1] === endToken && allowTrailingComma) {
304
+ break;
305
+ }
306
+
307
+ if (this.tokens.length <= 0) {
308
+ bail("Invalid type tag.");
309
+ }
310
+ }
311
+ return res;
312
+ }
313
+
314
+ parseTypeTag(): TypeTag {
315
+ if (this.tokens.length === 0) {
316
+ bail("Invalid type tag.");
317
+ }
318
+
319
+ // Pop left most element out
320
+ const [tokenTy, tokenVal] = this.tokens.shift()!;
321
+
322
+ if (tokenVal === "u8") {
323
+ return new TypeTagU8();
324
+ }
325
+ if (tokenVal === "u16") {
326
+ return new TypeTagU16();
327
+ }
328
+ if (tokenVal === "u32") {
329
+ return new TypeTagU32();
330
+ }
331
+ if (tokenVal === "u64") {
332
+ return new TypeTagU64();
333
+ }
334
+ if (tokenVal === "u128") {
335
+ return new TypeTagU128();
336
+ }
337
+ if (tokenVal === "u256") {
338
+ return new TypeTagU256();
339
+ }
340
+ if (tokenVal === "bool") {
341
+ return new TypeTagBool();
342
+ }
343
+ if (tokenVal === "address") {
344
+ return new TypeTagAddress();
345
+ }
346
+ if (tokenVal === "vector") {
347
+ this.consume("<");
348
+ const res = this.parseTypeTag();
349
+ this.consume(">");
350
+ return new TypeTagVector(res);
351
+ }
352
+ if (tokenVal === "string") {
353
+ return new TypeTagStruct(stringStructTag());
354
+ }
355
+ if (tokenTy === "IDENT" && (tokenVal.startsWith("0x") || tokenVal.startsWith("0X"))) {
356
+ const address = AccountAddress.fromHexInput(tokenVal);
357
+ this.consume("::");
358
+ const [moduleTokenTy, module] = this.tokens.shift()!;
359
+ if (moduleTokenTy !== "IDENT") {
360
+ bail("Invalid type tag.");
361
+ }
362
+ this.consume("::");
363
+ const [nameTokenTy, name] = this.tokens.shift()!;
364
+ if (nameTokenTy !== "IDENT") {
365
+ bail("Invalid type tag.");
366
+ }
367
+
368
+ // Objects can contain either concrete types e.g. 0x1::object::ObjectCore or generics e.g. T
369
+ // Neither matter as we can't do type checks, so just the address applies, and we consume the entire generic.
370
+ // TODO: Support parsing structs that don't come from core code address
371
+ if (AccountAddress.ONE.toString() === address.toString() && module === "object" && name === "Object") {
372
+ this.consumeWholeGeneric();
373
+ return new TypeTagAddress();
374
+ }
375
+
376
+ let tyTags: TypeTag[] = [];
377
+ // Check if the struct has ty args
378
+ if (this.tokens.length > 0 && this.tokens[0][1] === "<") {
379
+ this.consume("<");
380
+ tyTags = this.parseCommaList(">", true);
381
+ this.consume(">");
382
+ }
383
+
384
+ const structTag = new StructTag(address, new Identifier(module), new Identifier(name), tyTags);
385
+ return new TypeTagStruct(structTag);
386
+ }
387
+ if (tokenTy === "GENERIC") {
388
+ if (this.typeTags.length === 0) {
389
+ bail("Can't convert generic type since no typeTags were specified.");
390
+ }
391
+ // a generic tokenVal has the format of `T<digit>`, for example `T1`.
392
+ // The digit (i.e 1) indicates the index of this type in the typeTags array.
393
+ // For a tokenVal == T1, should be parsed as the type in typeTags[1]
394
+ const idx = parseInt(tokenVal.substring(1), 10);
395
+ return new TypeTagParser(this.typeTags[idx]).parseTypeTag();
396
+ }
397
+
398
+ throw new Error("Invalid type tag.");
399
+ }
400
+ }
401
+
402
+ export class TypeTagParserError extends Error {
403
+ constructor(message: string) {
404
+ super(message);
405
+ this.name = "TypeTagParserError";
406
+ }
407
+ }
408
+
409
+ function tokenize(tagStr: string): Token[] {
410
+ let pos = 0;
411
+ const tokens = [];
412
+ while (pos < tagStr.length) {
413
+ const [token, size] = nextToken(tagStr, pos);
414
+ if (token[0] !== "SPACE") {
415
+ tokens.push(token);
416
+ }
417
+ pos += size;
418
+ }
419
+ return tokens;
420
+ }
421
+
422
+ function bail(message: string) {
423
+ throw new TypeTagParserError(message);
424
+ }
425
+
426
+ function isWhiteSpace(c: string): boolean {
427
+ return !!c.match(/\s/);
428
+ }
429
+
430
+ function isValidAlphabetic(c: string): boolean {
431
+ return !!c.match(/[_A-Za-z0-9]/g);
432
+ }
433
+
434
+ // Generic format is T<digits> - for example T1, T2, T10
435
+ function isGeneric(c: string): boolean {
436
+ return !!c.match(/T\d+/g);
437
+ }
438
+
439
+ /**
440
+ * Used for parsing a TypeTag, a Token type is two strings: [token type, token value]
441
+ * @example const token: Token = ["COMMA", ","];
442
+ * @see nextToken(...) in typeTagParser.ts
443
+ */
444
+ type Token = [string, string];
445
+
446
+ // Returns Token and Token byte size
447
+ function nextToken(tagStr: string, pos: number): [Token, number] {
448
+ const c = tagStr[pos];
449
+ if (c === ":") {
450
+ if (tagStr.slice(pos, pos + 2) === "::") {
451
+ return [["COLON", "::"], 2];
452
+ }
453
+ bail("Unrecognized token.");
454
+ } else if (c === "<") {
455
+ return [["LT", "<"], 1];
456
+ } else if (c === ">") {
457
+ return [["GT", ">"], 1];
458
+ } else if (c === ",") {
459
+ return [["COMMA", ","], 1];
460
+ } else if (isWhiteSpace(c)) {
461
+ let res = "";
462
+ for (let i = pos; i < tagStr.length; i += 1) {
463
+ const char = tagStr[i];
464
+ if (isWhiteSpace(char)) {
465
+ res = `${res}${char}`;
466
+ } else {
467
+ break;
468
+ }
469
+ }
470
+ return [["SPACE", res], res.length];
471
+ } else if (isValidAlphabetic(c)) {
472
+ let res = "";
473
+ for (let i = pos; i < tagStr.length; i += 1) {
474
+ const char = tagStr[i];
475
+ if (isValidAlphabetic(char)) {
476
+ res = `${res}${char}`;
477
+ } else {
478
+ break;
479
+ }
480
+ }
481
+ if (isGeneric(res)) {
482
+ return [["GENERIC", res], res.length];
483
+ }
484
+ return [["IDENT", res], res.length];
485
+ }
486
+ throw new Error("Unrecognized token.");
487
+ }