@typesol/cli 0.18.0 → 0.20.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.
package/lib/typesol.d.ts CHANGED
@@ -517,6 +517,20 @@ export type InitIfNeeded<T> = T extends TokenAccount
517
517
  freezeAuthority: Pubkey | null,
518
518
  tokenProgram?: TokenProgram | Token2022Program | TokenInterface,
519
519
  ): boolean;
520
+ /**
521
+ * With extensions: created with them, or an existing mint must carry them with these keys, as Anchor's
522
+ * `extensions::…` constraints check (2024–2039). groupPointer, groupMemberPointer, metadataPointer,
523
+ * closeAuthority, permanentDelegate and transferHook only.
524
+ */
525
+ createIfNeeded(
526
+ payer: Mut<Signer>,
527
+ seeds: Seed[] | null,
528
+ decimals: u8,
529
+ mintAuthority: Pubkey,
530
+ freezeAuthority: Pubkey | null,
531
+ extensions: MintExtensions,
532
+ tokenProgram?: Token2022Program | TokenInterface,
533
+ ): boolean;
520
534
  readonly pdaBump: u8;
521
535
  }
522
536
  : T &
@@ -539,6 +553,15 @@ export type InitIfNeeded<T> = T extends TokenAccount
539
553
  * They nest: `CloseTo<HasOne<Mut<Vault>, "owner">, "owner">`.
540
554
  */
541
555
  export type HasOne<A, Field extends string> = A & { readonly __hasOne?: Field };
556
+ /**
557
+ * Anchor's `token::mint = mintParam, token::authority = authorityParam` on an existing token account, naming the
558
+ * parameters (2014 / 2015); `never` leaves one out.
559
+ */
560
+ export type TokenOf<A, MintParam extends string, AuthorityParam extends string = never> = A & { readonly __tokenOf?: [MintParam, AuthorityParam] };
561
+ /** Anchor's `mint::authority = a, mint::freeze_authority = f` on an existing mint, naming the parameters (2016 / 2017). */
562
+ export type MintOf<A, AuthorityParam extends string, FreezeAuthorityParam extends string = never> = A & {
563
+ readonly __mintOf?: [AuthorityParam, FreezeAuthorityParam];
564
+ };
542
565
  export type Seeds<A, Names extends readonly string[], Bump extends string = never, ProgramId extends string = never> = A & {
543
566
  readonly __seeds?: [Names, Bump, ProgramId];
544
567
  /** The PDA's bump (Anchor `ctx.bumps.<account>`): the stored bump field when one is named, else the canonical bump found. */
@@ -774,6 +797,31 @@ export interface BubblegumProgram extends AccountMeta {
774
797
  sellerFeeBasisPoints: u16,
775
798
  signerSeeds?: Seed[] | SignerSeeds,
776
799
  ): void;
800
+ /**
801
+ * MintToCollectionV1 on a V1 tree: the leaf joins a Token Metadata collection (Bubblegum verifies it; the collection
802
+ * authority signs, its record PDA is `null` when it is the update authority itself). Creators default to none,
803
+ * `isMutable` to true, `editionNonce` to None.
804
+ */
805
+ mintToCollection(
806
+ treeConfig: AccountMeta,
807
+ leafOwner: AccountMeta,
808
+ leafDelegate: AccountMeta,
809
+ merkleTree: AccountMeta,
810
+ payer: Signer,
811
+ treeDelegate: AccountMeta,
812
+ collectionAuthority: AccountMeta,
813
+ collectionAuthorityRecordPda: AccountMeta | null,
814
+ collectionMint: AccountMeta,
815
+ collectionMetadata: AccountMeta,
816
+ collectionEdition: AccountMeta,
817
+ bubblegumSigner: AccountMeta,
818
+ logWrapper: AccountMeta,
819
+ compressionProgram: AccountMeta,
820
+ tokenMetadataProgram: AccountMeta,
821
+ systemProgram: SystemProgram,
822
+ metadata: CompressedMetadata & { editionNonce?: u8 },
823
+ signerSeeds?: Seed[] | SignerSeeds,
824
+ ): void;
777
825
  /**
778
826
  * CreateTreeConfigV2: a tree on mpl-account-compression (mcmt6…, allocated by the client and owned by it) with the
779
827
  * mpl-noop log wrapper (mnoop…). `treeCreator` `null`: the payer.
@@ -1382,7 +1430,90 @@ export declare function invoke(
1382
1430
  ): void;
1383
1431
 
1384
1432
  /** Abort with the given error unless `condition` holds. Use a string enum member or a string literal. */
1385
- export declare function require(condition: boolean, error: string): asserts condition;
1433
+ /**
1434
+ * Anchor's own error codes (anchor-lang `ErrorCode`): `require(condition, AnchorError.AccountDidNotDeserialize)` fails
1435
+ * with that code, as `require!(condition, ErrorCode::AccountDidNotDeserialize)` does. Not listed in the IDL's errors.
1436
+ */
1437
+ export declare enum AnchorError {
1438
+ InstructionMissing = 100,
1439
+ InstructionFallbackNotFound = 101,
1440
+ InstructionDidNotDeserialize = 102,
1441
+ InstructionDidNotSerialize = 103,
1442
+ IdlInstructionStub = 1000,
1443
+ IdlInstructionInvalidProgram = 1001,
1444
+ IdlAccountNotEmpty = 1002,
1445
+ EventInstructionStub = 1500,
1446
+ ConstraintMut = 2000,
1447
+ ConstraintHasOne = 2001,
1448
+ ConstraintSigner = 2002,
1449
+ ConstraintRaw = 2003,
1450
+ ConstraintOwner = 2004,
1451
+ ConstraintRentExempt = 2005,
1452
+ ConstraintSeeds = 2006,
1453
+ ConstraintExecutable = 2007,
1454
+ ConstraintState = 2008,
1455
+ ConstraintAssociated = 2009,
1456
+ ConstraintAssociatedInit = 2010,
1457
+ ConstraintClose = 2011,
1458
+ ConstraintAddress = 2012,
1459
+ ConstraintZero = 2013,
1460
+ ConstraintTokenMint = 2014,
1461
+ ConstraintTokenOwner = 2015,
1462
+ ConstraintMintMintAuthority = 2016,
1463
+ ConstraintMintFreezeAuthority = 2017,
1464
+ ConstraintMintDecimals = 2018,
1465
+ ConstraintSpace = 2019,
1466
+ ConstraintAccountIsNone = 2020,
1467
+ ConstraintTokenTokenProgram = 2021,
1468
+ ConstraintMintTokenProgram = 2022,
1469
+ ConstraintAssociatedTokenTokenProgram = 2023,
1470
+ ConstraintMintGroupPointerExtension = 2024,
1471
+ ConstraintMintGroupPointerExtensionAuthority = 2025,
1472
+ ConstraintMintGroupPointerExtensionGroupAddress = 2026,
1473
+ ConstraintMintGroupMemberPointerExtension = 2027,
1474
+ ConstraintMintGroupMemberPointerExtensionAuthority = 2028,
1475
+ ConstraintMintGroupMemberPointerExtensionMemberAddress = 2029,
1476
+ ConstraintMintMetadataPointerExtension = 2030,
1477
+ ConstraintMintMetadataPointerExtensionAuthority = 2031,
1478
+ ConstraintMintMetadataPointerExtensionMetadataAddress = 2032,
1479
+ ConstraintMintCloseAuthorityExtension = 2033,
1480
+ ConstraintMintCloseAuthorityExtensionAuthority = 2034,
1481
+ ConstraintMintPermanentDelegateExtension = 2035,
1482
+ ConstraintMintPermanentDelegateExtensionDelegate = 2036,
1483
+ ConstraintMintTransferHookExtension = 2037,
1484
+ ConstraintMintTransferHookExtensionAuthority = 2038,
1485
+ ConstraintMintTransferHookExtensionProgramId = 2039,
1486
+ RequireViolated = 2500,
1487
+ RequireEqViolated = 2501,
1488
+ RequireKeysEqViolated = 2502,
1489
+ RequireNeqViolated = 2503,
1490
+ RequireKeysNeqViolated = 2504,
1491
+ RequireGtViolated = 2505,
1492
+ RequireGteViolated = 2506,
1493
+ AccountDiscriminatorAlreadySet = 3000,
1494
+ AccountDiscriminatorNotFound = 3001,
1495
+ AccountDiscriminatorMismatch = 3002,
1496
+ AccountDidNotDeserialize = 3003,
1497
+ AccountDidNotSerialize = 3004,
1498
+ AccountNotEnoughKeys = 3005,
1499
+ AccountNotMutable = 3006,
1500
+ AccountOwnedByWrongProgram = 3007,
1501
+ InvalidProgramId = 3008,
1502
+ InvalidProgramExecutable = 3009,
1503
+ AccountNotSigner = 3010,
1504
+ AccountNotSystemOwned = 3011,
1505
+ AccountNotInitialized = 3012,
1506
+ AccountNotProgramData = 3013,
1507
+ AccountNotAssociatedTokenAccount = 3014,
1508
+ AccountSysvarMismatch = 3015,
1509
+ AccountReallocExceedsLimit = 3016,
1510
+ AccountDuplicateReallocs = 3017,
1511
+ DeclaredProgramIdMismatch = 4100,
1512
+ TryingToInitPayerAsProgramAccount = 4101,
1513
+ InvalidNumericConversion = 4102,
1514
+ Deprecated = 5000,
1515
+ }
1516
+ export declare function require(condition: boolean, error: string | AnchorError): asserts condition;
1386
1517
 
1387
1518
  /** Write a string, integer or pubkey to the program log. */
1388
1519
  export declare function log(value: string | bigint | Pubkey | Hash): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typesol/cli",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "Compile a TypeScript-syntax language directly to Solana SBF programs.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1105,48 +1105,124 @@ static inline uint64_t ts_alloc(uint64_t n, uint8_t **out) {
1105
1105
  static uint64_t ts_base58_32(const uint8_t *in, TS_Str *out) {
1106
1106
  static const char digits[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
1107
1107
  const uint64_t D = 656356768ULL; /* 58^5 */
1108
- uint32_t limb[8];
1109
- for (int i = 0; i < 8; i++)
1110
- limb[i] = (uint32_t)in[4 * i] << 24 | (uint32_t)in[4 * i + 1] << 16 | (uint32_t)in[4 * i + 2] << 8 | (uint32_t)in[4 * i + 3];
1111
- uint8_t rev[50]; /* base-58 digits, least significant first; 32 bytes need at most 44 */
1112
- uint64_t len = 0;
1108
+ uint64_t limb[8];
1109
+ for (int i = 0; i < 8; i++) limb[i] = __builtin_bswap32(*(const ts_u32_unaligned *)(in + 4 * i)); /* big-endian words */
1110
+ /* Digits are written as characters from the end of `buf`, five per pass; 32 bytes need at most 44. */
1111
+ char buf[50];
1112
+ uint64_t pos = sizeof(buf);
1113
1113
  int start = 0;
1114
1114
  while (start < 8 && limb[start] == 0) start++;
1115
1115
  while (start < 8) {
1116
1116
  uint64_t rem = 0;
1117
- for (int i = start; i < 8; i++) {
1118
- uint64_t cur = (rem << 32) | limb[i];
1119
- uint64_t q = cur / D;
1120
- rem = cur - q * D;
1121
- limb[i] = (uint32_t)q;
1117
+ /* One long-division pass from the first nonzero limb, unrolled. */
1118
+ #define TS_B58_STEP(i) \
1119
+ { \
1120
+ uint64_t cur = (rem << 32) | limb[i]; \
1121
+ uint64_t q = cur / D; \
1122
+ rem = cur - q * D; \
1123
+ limb[i] = q; \
1124
+ }
1125
+ switch (start) {
1126
+ case 0: TS_B58_STEP(0) /* fallthrough */
1127
+ case 1: TS_B58_STEP(1) /* fallthrough */
1128
+ case 2: TS_B58_STEP(2) /* fallthrough */
1129
+ case 3: TS_B58_STEP(3) /* fallthrough */
1130
+ case 4: TS_B58_STEP(4) /* fallthrough */
1131
+ case 5: TS_B58_STEP(5) /* fallthrough */
1132
+ case 6: TS_B58_STEP(6) /* fallthrough */
1133
+ default: TS_B58_STEP(7)
1122
1134
  }
1135
+ #undef TS_B58_STEP
1123
1136
  while (start < 8 && limb[start] == 0) start++;
1124
- for (int k = 0; k < 5; k++) {
1125
- uint64_t q = rem / 58;
1126
- rev[len++] = (uint8_t)(rem - q * 58);
1127
- rem = q;
1128
- }
1137
+ uint64_t q;
1138
+ q = rem / 58; buf[--pos] = digits[rem - q * 58]; rem = q;
1139
+ q = rem / 58; buf[--pos] = digits[rem - q * 58]; rem = q;
1140
+ q = rem / 58; buf[--pos] = digits[rem - q * 58]; rem = q;
1141
+ q = rem / 58; buf[--pos] = digits[rem - q * 58]; rem = q;
1142
+ buf[--pos] = digits[rem];
1129
1143
  }
1130
- while (len > 0 && rev[len - 1] == 0) len--;
1144
+ /* Leading zero digits of the number are not printed; each leading zero byte is a '1'. */
1145
+ while (pos < sizeof(buf) && buf[pos] == '1') pos++;
1131
1146
  uint64_t zeros = 0;
1132
1147
  while (zeros < 32 && in[zeros] == 0) zeros++;
1148
+ uint64_t len = sizeof(buf) - pos;
1133
1149
  uint8_t *p;
1134
1150
  TS_TRY(ts_alloc(zeros + len, &p));
1135
1151
  for (uint64_t i = 0; i < zeros; i++) p[i] = '1';
1136
- for (uint64_t j = 0; j < len; j++) p[zeros + j] = (uint8_t)digits[rev[len - 1 - j]];
1152
+ ts_memcpy(p + zeros, buf + pos, len);
1137
1153
  *out = ts_str(p, zeros + len);
1138
1154
  return SUCCESS;
1139
1155
  }
1140
1156
 
1141
- static inline uint64_t ts_str_concat(TS_Str a, TS_Str b, TS_Str *out) {
1157
+ /*
1158
+ * `s += …` on a local string: the pieces are copied right after `s` when it ends where the heap's free space starts
1159
+ * (it was the last thing allocated), and `s` grows in place; otherwise `s` and the pieces are joined into a new string.
1160
+ * Other views of the old `s` keep their length, so they still read the same bytes. The bytes written are past the
1161
+ * heap's top, where no view can point (ts_alloc is the only source of heap pointers and never hands out memory past
1162
+ * the top), so no piece is overwritten while it is copied.
1163
+ */
1164
+ static uint64_t ts_str_append_parts(TS_Str *s, const TS_Str *parts, uint64_t n) {
1165
+ uint64_t *next = (uint64_t *)HEAP_START_ADDRESS;
1166
+ uint64_t add = 0;
1167
+ for (uint64_t i = 0; i < n; i++) add += parts[i].len;
1168
+ if (*next != 0 && s->len > 0 && (uint64_t)(s->ptr + s->len) == HEAP_START_ADDRESS + *next && *next + add <= TS_HEAP_LENGTH) {
1169
+ for (uint64_t i = 0; i < n; i++) {
1170
+ ts_memcpy((uint8_t *)s->ptr + s->len, parts[i].ptr, parts[i].len);
1171
+ s->len += parts[i].len;
1172
+ }
1173
+ *next += add;
1174
+ return SUCCESS;
1175
+ }
1142
1176
  uint8_t *p;
1143
- TS_TRY(ts_alloc(a.len + b.len, &p));
1144
- ts_memcpy(p, a.ptr, a.len);
1145
- ts_memcpy(p + a.len, b.ptr, b.len);
1146
- *out = ts_str(p, a.len + b.len);
1177
+ TS_TRY(ts_alloc(s->len + add, &p));
1178
+ ts_memcpy(p, s->ptr, s->len);
1179
+ uint64_t at = s->len;
1180
+ for (uint64_t i = 0; i < n; i++) {
1181
+ ts_memcpy(p + at, parts[i].ptr, parts[i].len);
1182
+ at += parts[i].len;
1183
+ }
1184
+ *s = ts_str(p, at);
1147
1185
  return SUCCESS;
1148
1186
  }
1149
1187
 
1188
+ /* `s += b` (and `a + b`, with `s` a copy of `a`): the one-piece case of ts_str_append_parts. */
1189
+ static uint64_t ts_str_append(TS_Str *s, TS_Str b) {
1190
+ uint64_t *next = (uint64_t *)HEAP_START_ADDRESS;
1191
+ if (*next != 0 && s->len > 0 && (uint64_t)(s->ptr + s->len) == HEAP_START_ADDRESS + *next && *next + b.len <= TS_HEAP_LENGTH) {
1192
+ ts_memcpy((uint8_t *)s->ptr + s->len, b.ptr, b.len);
1193
+ *next += b.len;
1194
+ s->len += b.len;
1195
+ return SUCCESS;
1196
+ }
1197
+ uint8_t *p;
1198
+ TS_TRY(ts_alloc(s->len + b.len, &p));
1199
+ ts_memcpy(p, s->ptr, s->len);
1200
+ ts_memcpy(p + s->len, b.ptr, b.len);
1201
+ *s = ts_str(p, s->len + b.len);
1202
+ return SUCCESS;
1203
+ }
1204
+
1205
+ /* The pieces of a template literal, joined with one heap allocation and one copy each. */
1206
+ static uint64_t ts_str_join(const TS_Str *parts, uint64_t n, TS_Str *out) {
1207
+ uint64_t total = 0;
1208
+ for (uint64_t i = 0; i < n; i++) total += parts[i].len;
1209
+ uint8_t *p;
1210
+ TS_TRY(ts_alloc(total, &p));
1211
+ uint64_t at = 0;
1212
+ for (uint64_t i = 0; i < n; i++) {
1213
+ ts_memcpy(p + at, parts[i].ptr, parts[i].len);
1214
+ at += parts[i].len;
1215
+ }
1216
+ *out = ts_str(p, total);
1217
+ return SUCCESS;
1218
+ }
1219
+
1220
+ /* `a + b`: a new string (`a` grows in place when it is the newest heap string; its own view keeps its length). */
1221
+ static inline uint64_t ts_str_concat(TS_Str a, TS_Str b, TS_Str *out) {
1222
+ *out = a;
1223
+ return ts_str_append(out, b);
1224
+ }
1225
+
1150
1226
  /* Decimal text of an integer, on the heap. */
1151
1227
  /* Copy a string's bytes to the heap (a stable value, independent of where the view pointed). */
1152
1228
  static inline uint64_t ts_str_copy(TS_Str a, TS_Str *out) {