@typesol/cli 0.16.0 → 0.17.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
@@ -77,6 +77,24 @@ export interface Vec<T> {
77
77
  [Symbol.iterator](): Iterator<T>;
78
78
  }
79
79
 
80
+ /**
81
+ * A list stored inline with room for N elements: a u32 length, then N slots (Anchor `Vec<T>` with `#[max_len(N)]`, but
82
+ * always 4 + N × size(T) bytes). Unlike `Vec<T>` it can be any field, any number of times, and in nested structs;
83
+ * `push` fails (5104) when it is full. Write a whole one with `fixedVec([a, b])`.
84
+ */
85
+ export interface FixedVec<T, N extends number> {
86
+ readonly length: u64;
87
+ get(index: bigint): T;
88
+ set(index: bigint, value: T): void;
89
+ push(value: T): void;
90
+ pop(): T;
91
+ clear(): void;
92
+ [Symbol.iterator](): Iterator<T>;
93
+ readonly __capacity?: N;
94
+ }
95
+ /** A FixedVec value holding these elements (`acct.owners = fixedVec([a, b])`, `{ owners: fixedVec([]) }`). */
96
+ export declare function fixedVec<T>(items: T[]): FixedVec<T, never>;
97
+
80
98
  /** One extra account passed after the declared ones. Nothing about it is checked until you check it. */
81
99
  export interface RemainingAccount {
82
100
  readonly key: Pubkey;
@@ -233,7 +251,10 @@ export interface TokenMetadataProgram extends AccountMeta {
233
251
  isMutable: boolean,
234
252
  signerSeeds?: Seed[] | SignerSeeds,
235
253
  ): void;
236
- /** With creators (1–5, shares adding up to 100) and/or an unverified collection mint. */
254
+ /**
255
+ * With creators (1–5, shares adding up to 100), an unverified collection mint, and/or `isCollection: true`
256
+ * (CollectionDetails::V1: this NFT is a sized collection other NFTs are verified into).
257
+ */
237
258
  createV3(
238
259
  metadata: AccountMeta,
239
260
  mint: AccountMeta,
@@ -246,10 +267,42 @@ export interface TokenMetadataProgram extends AccountMeta {
246
267
  uri: string,
247
268
  sellerFeeBasisPoints: u16,
248
269
  isMutable: boolean,
249
- extras: { creators?: MetadataCreator[]; collection?: Pubkey },
270
+ extras: { creators?: MetadataCreator[]; collection?: Pubkey; isCollection?: boolean },
271
+ signerSeeds?: Seed[] | SignerSeeds,
272
+ ): void;
273
+ /**
274
+ * CreateMasterEditionV3: makes `mint` (supply 1, decimals 0) a master edition; the mint and freeze authorities move
275
+ * to the edition. `maxSupply` 0n is a one of one, `null` allows unlimited prints.
276
+ */
277
+ createMasterEditionV3(
278
+ edition: AccountMeta,
279
+ mint: AccountMeta,
280
+ updateAuthority: AccountMeta,
281
+ mintAuthority: AccountMeta,
282
+ payer: Mut<Signer>,
283
+ metadata: AccountMeta,
284
+ tokenProgram: TokenProgram,
285
+ systemProgram: SystemProgram,
286
+ maxSupply: u64 | null,
287
+ signerSeeds?: Seed[] | SignerSeeds,
288
+ ): void;
289
+ /**
290
+ * Verify with CollectionV1: marks `metadata`'s collection (set with createV3's `collection`) verified. `authority` is
291
+ * the collection's update authority; the collection is a master edition created with `isCollection: true`.
292
+ */
293
+ verifyCollection(
294
+ authority: AccountMeta,
295
+ metadata: AccountMeta,
296
+ collectionMint: AccountMeta,
297
+ collectionMetadata: AccountMeta,
298
+ collectionMasterEdition: AccountMeta,
299
+ systemProgram: SystemProgram,
300
+ instructionsSysvar: AccountMeta,
250
301
  signerSeeds?: Seed[] | SignerSeeds,
251
302
  ): void;
252
303
  }
304
+ /** The Metaplex master edition address of a mint (PDA ["metadata", program, mint, "edition"]). */
305
+ export declare function masterEditionAddress(mint: Pubkey): Pubkey;
253
306
  /** The canonical program address of `seeds` under `program` (Rust `Pubkey::find_program_address(seeds, program).0`). */
254
307
  export declare function findProgramAddress(seeds: Seed[], program: Pubkey): Pubkey;
255
308
  /** The Metaplex metadata account address of a mint. */
@@ -473,9 +526,36 @@ export declare function emitCpi<T>(event: T, eventAuthority: EventAuthority, sel
473
526
  * account out. Accounts that sign (the new asset/collection, authorities) are keypair Signers, or PDAs of this
474
527
  * program covered by `signerSeeds`.
475
528
  */
529
+ /**
530
+ * Who manages a Metaplex Core plugin: `"owner"`, `"updateAuthority"`, `"none"` (nobody: fixed), or an address. Left out,
531
+ * the plugin type's default (the owner for owner-managed plugins, the update authority for the others).
532
+ */
533
+ export type CorePluginAuthority = "none" | "owner" | "updateAuthority" | Pubkey;
534
+ /** A Metaplex Core plugin, written as an object literal (Core's Plugin enum, with its authority when it is added). */
535
+ export type CorePlugin = (
536
+ | { kind: "Royalties"; basisPoints: u16; creators: { address: Pubkey; percentage: u8 }[] }
537
+ | { kind: "FreezeDelegate"; frozen: boolean }
538
+ | { kind: "BurnDelegate" }
539
+ | { kind: "TransferDelegate" }
540
+ | { kind: "UpdateDelegate"; additionalDelegates?: Pubkey[] }
541
+ | { kind: "PermanentFreezeDelegate"; frozen: boolean }
542
+ | { kind: "Attributes"; attributes: { key: string; value: string }[] }
543
+ | { kind: "PermanentTransferDelegate" }
544
+ | { kind: "PermanentBurnDelegate" }
545
+ | { kind: "Edition"; number: u32 }
546
+ | { kind: "AddBlocker" }
547
+ | { kind: "ImmutableMetadata" }
548
+ /** On a collection: lets Bubblegum mint compressed NFTs into it (mintV2 with a collection). */
549
+ | { kind: "BubblegumV2" }
550
+ ) & { authority?: CorePluginAuthority };
551
+ export type CorePluginKind = CorePlugin["kind"] | "MasterEdition" | "VerifiedCreators" | "Autograph";
552
+
476
553
  export interface MplCoreProgram extends AccountMeta {
477
554
  readonly __mpl_core: void;
478
- /** CreateV1. In a collection, `authority` is the collection's update authority; `owner` defaults to the payer. */
555
+ /**
556
+ * CreateV1. In a collection, `authority` is the collection's update authority; `owner` defaults to the payer.
557
+ * `plugins` (a literal list, one of each kind) are created with the asset.
558
+ */
479
559
  createAsset(
480
560
  asset: AccountMeta,
481
561
  collection: AccountMeta | null,
@@ -487,6 +567,28 @@ export interface MplCoreProgram extends AccountMeta {
487
567
  uri: string,
488
568
  signerSeeds?: Seed[] | SignerSeeds,
489
569
  ): void;
570
+ createAsset(
571
+ asset: AccountMeta,
572
+ collection: AccountMeta | null,
573
+ authority: AccountMeta | null,
574
+ payer: Mut<Signer>,
575
+ owner: AccountMeta | null,
576
+ systemProgram: SystemProgram,
577
+ name: string,
578
+ uri: string,
579
+ plugins: CorePlugin[],
580
+ signerSeeds?: Seed[] | SignerSeeds,
581
+ ): void;
582
+ createCollection(
583
+ collection: AccountMeta,
584
+ updateAuthority: AccountMeta | null,
585
+ payer: Mut<Signer>,
586
+ systemProgram: SystemProgram,
587
+ name: string,
588
+ uri: string,
589
+ signerSeeds?: Seed[] | SignerSeeds,
590
+ ): void;
591
+ /** With plugins every asset of the collection inherits (Royalties, PermanentFreezeDelegate, …). */
490
592
  createCollection(
491
593
  collection: AccountMeta,
492
594
  updateAuthority: AccountMeta | null,
@@ -494,6 +596,60 @@ export interface MplCoreProgram extends AccountMeta {
494
596
  systemProgram: SystemProgram,
495
597
  name: string,
496
598
  uri: string,
599
+ plugins: CorePlugin[],
600
+ signerSeeds?: Seed[] | SignerSeeds,
601
+ ): void;
602
+ /** AddPluginV1, signed by `authority` (`null`: the payer): the owner for owner-managed plugins, else the update authority. */
603
+ addPlugin(
604
+ asset: AccountMeta,
605
+ collection: AccountMeta | null,
606
+ payer: Mut<Signer>,
607
+ authority: AccountMeta | null,
608
+ systemProgram: SystemProgram,
609
+ plugin: CorePlugin,
610
+ signerSeeds?: Seed[] | SignerSeeds,
611
+ ): void;
612
+ /** UpdatePluginV1: new values for a plugin the asset has (no `authority`), e.g. `{ kind: "FreezeDelegate", frozen: true }`. */
613
+ updatePlugin(
614
+ asset: AccountMeta,
615
+ collection: AccountMeta | null,
616
+ payer: Mut<Signer>,
617
+ authority: AccountMeta | null,
618
+ systemProgram: SystemProgram,
619
+ plugin: CorePlugin,
620
+ signerSeeds?: Seed[] | SignerSeeds,
621
+ ): void;
622
+ removePlugin(
623
+ asset: AccountMeta,
624
+ collection: AccountMeta | null,
625
+ payer: Mut<Signer>,
626
+ authority: AccountMeta | null,
627
+ systemProgram: SystemProgram,
628
+ kind: CorePluginKind,
629
+ signerSeeds?: Seed[] | SignerSeeds,
630
+ ): void;
631
+ addCollectionPlugin(
632
+ collection: AccountMeta,
633
+ payer: Mut<Signer>,
634
+ authority: AccountMeta | null,
635
+ systemProgram: SystemProgram,
636
+ plugin: CorePlugin,
637
+ signerSeeds?: Seed[] | SignerSeeds,
638
+ ): void;
639
+ updateCollectionPlugin(
640
+ collection: AccountMeta,
641
+ payer: Mut<Signer>,
642
+ authority: AccountMeta | null,
643
+ systemProgram: SystemProgram,
644
+ plugin: CorePlugin,
645
+ signerSeeds?: Seed[] | SignerSeeds,
646
+ ): void;
647
+ removeCollectionPlugin(
648
+ collection: AccountMeta,
649
+ payer: Mut<Signer>,
650
+ authority: AccountMeta | null,
651
+ systemProgram: SystemProgram,
652
+ kind: CorePluginKind,
497
653
  signerSeeds?: Seed[] | SignerSeeds,
498
654
  ): void;
499
655
  /** TransferV1, signed by the owner (or a delegate) as `authority` (`null`: the payer). */
@@ -548,6 +704,106 @@ export interface BubblegumProgram extends AccountMeta {
548
704
  sellerFeeBasisPoints: u16,
549
705
  signerSeeds?: Seed[] | SignerSeeds,
550
706
  ): void;
707
+ /**
708
+ * CreateTreeConfigV2: a tree on mpl-account-compression (mcmt6…, allocated by the client and owned by it) with the
709
+ * mpl-noop log wrapper (mnoop…). `treeCreator` `null`: the payer.
710
+ */
711
+ createTreeV2(
712
+ treeConfig: AccountMeta,
713
+ merkleTree: AccountMeta,
714
+ payer: Mut<Signer>,
715
+ treeCreator: AccountMeta | null,
716
+ logWrapper: AccountMeta,
717
+ compressionProgram: AccountMeta,
718
+ systemProgram: SystemProgram,
719
+ maxDepth: u32,
720
+ maxBufferSize: u32,
721
+ isPublic: boolean,
722
+ signerSeeds?: Seed[] | SignerSeeds,
723
+ ): void;
724
+ /** MintV2 of a leaf, optionally into a Metaplex Core collection (whose update authority signs as `authority`). */
725
+ mintV2(
726
+ treeConfig: AccountMeta,
727
+ payer: Mut<Signer>,
728
+ treeDelegate: AccountMeta | null,
729
+ leafOwner: AccountMeta,
730
+ leafDelegate: AccountMeta | null,
731
+ merkleTree: AccountMeta,
732
+ logWrapper: AccountMeta,
733
+ compressionProgram: AccountMeta,
734
+ mplCoreProgram: AccountMeta,
735
+ systemProgram: SystemProgram,
736
+ metadata: CompressedMetadata,
737
+ signerSeeds?: Seed[] | SignerSeeds,
738
+ ): void;
739
+ mintV2(
740
+ treeConfig: AccountMeta,
741
+ payer: Mut<Signer>,
742
+ treeDelegate: AccountMeta | null,
743
+ leafOwner: AccountMeta,
744
+ leafDelegate: AccountMeta | null,
745
+ merkleTree: AccountMeta,
746
+ logWrapper: AccountMeta,
747
+ compressionProgram: AccountMeta,
748
+ mplCoreProgram: AccountMeta,
749
+ systemProgram: SystemProgram,
750
+ metadata: CompressedMetadata,
751
+ collection: { collection: AccountMeta; authority: AccountMeta; cpiSigner: AccountMeta },
752
+ signerSeeds?: Seed[] | SignerSeeds,
753
+ ): void;
754
+ /** TransferV2, signed by the owner or delegate as `authority` (`null`: the payer); `proof` is the leaf's Merkle proof. */
755
+ transferV2(
756
+ treeConfig: AccountMeta,
757
+ payer: Mut<Signer>,
758
+ authority: AccountMeta | null,
759
+ leafOwner: AccountMeta,
760
+ leafDelegate: AccountMeta | null,
761
+ newLeafOwner: AccountMeta,
762
+ merkleTree: AccountMeta,
763
+ coreCollection: AccountMeta | null,
764
+ logWrapper: AccountMeta,
765
+ compressionProgram: AccountMeta,
766
+ systemProgram: SystemProgram,
767
+ leaf: CompressedLeaf,
768
+ proof: RemainingAccounts | RemainingSlice,
769
+ signerSeeds?: Seed[] | SignerSeeds,
770
+ ): void;
771
+ burnV2(
772
+ treeConfig: AccountMeta,
773
+ payer: Mut<Signer>,
774
+ authority: AccountMeta | null,
775
+ leafOwner: AccountMeta,
776
+ leafDelegate: AccountMeta | null,
777
+ merkleTree: AccountMeta,
778
+ coreCollection: AccountMeta | null,
779
+ mplCoreCpiSigner: AccountMeta | null,
780
+ logWrapper: AccountMeta,
781
+ compressionProgram: AccountMeta,
782
+ mplCoreProgram: AccountMeta,
783
+ systemProgram: SystemProgram,
784
+ leaf: CompressedLeaf,
785
+ proof: RemainingAccounts | RemainingSlice,
786
+ signerSeeds?: Seed[] | SignerSeeds,
787
+ ): void;
788
+ }
789
+ /** Bubblegum V2 leaf metadata (MetadataArgsV2): non-fungible, primary sale not happened, mutable unless `isMutable: false`. */
790
+ export interface CompressedMetadata {
791
+ name: string;
792
+ symbol: string;
793
+ uri: string;
794
+ sellerFeeBasisPoints: u16;
795
+ creators?: { address: Pubkey; verified: boolean; share: u8 }[];
796
+ isMutable?: boolean;
797
+ }
798
+ /** The leaf a transfer or burn replaces, as an indexer (DAS getAssetProof / getAsset) reports it. */
799
+ export interface CompressedLeaf {
800
+ root: Hash;
801
+ dataHash: Hash;
802
+ creatorHash: Hash;
803
+ assetDataHash?: Hash | null;
804
+ flags?: u8 | null;
805
+ nonce: u64;
806
+ index: u32;
551
807
  }
552
808
 
553
809
  /** The current slot and epoch (Clock sysvar). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typesol/cli",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "Compile a TypeScript-syntax language directly to Solana SBF programs.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,6 +34,7 @@
34
34
  #define TS_ERR_ALREADY_INITIALIZED 3000 /* AccountDiscriminatorAlreadySet */
35
35
  #define TS_ERR_DISCRIMINATOR 3002 /* AccountDiscriminatorMismatch */
36
36
  #define TS_ERR_ACCOUNT_TOO_SMALL 3003 /* AccountDidNotDeserialize */
37
+ #define TS_ERR_DID_NOT_SERIALIZE 3004 /* AccountDidNotSerialize */
37
38
  #define TS_ERR_TOKEN_ACCOUNT 3003 /* AccountDidNotDeserialize (not an initialized token account) */
38
39
  #define TS_ERR_MINT 3003 /* AccountDidNotDeserialize (not an initialized mint) */
39
40
  #define TS_ERR_NOT_ENOUGH_ACCOUNTS 3005 /* AccountNotEnoughKeys */
@@ -162,8 +163,11 @@ static inline TS_Str ts_str(const uint8_t *ptr, uint64_t len) {
162
163
  static inline bool ts_utf8_valid(const uint8_t *p, uint64_t n) {
163
164
  uint64_t i = 0;
164
165
  while (i < n) {
166
+ /* ASCII eight bytes at a time (no high bit set), then byte by byte up to the next multi-byte sequence. */
167
+ while (i + 8 <= n && (ts_ld64(p + i) & 0x8080808080808080ULL) == 0) i += 8;
168
+ while (i < n && p[i] < 0x80) i++;
169
+ if (i == n) break;
165
170
  uint8_t c = p[i];
166
- if (c < 0x80) { i++; continue; }
167
171
  uint64_t len;
168
172
  uint32_t cp;
169
173
  if (c >= 0xc2 && c <= 0xdf) { len = 2; cp = c & 0x1f; }
@@ -670,16 +674,17 @@ static inline uint64_t ts_realloc(TsParams *params, TsAccount *payer, TsAccount
670
674
  return ts_resize(params, payer, acct, new_len, entry_len);
671
675
  }
672
676
 
677
+ /* `space` for a new account; an existing one needs `min_space` (less for a @layout borsh account). */
673
678
  static inline uint64_t ts_create_pda_if_needed(TsParams *params, TsAccount *payer, TsAccount *acct,
674
679
  SolSignerSeed *seeds, int n, const uint8_t disc[8], uint64_t space,
675
- uint8_t *bump_out, bool *created) {
680
+ uint64_t min_space, uint8_t *bump_out, bool *created) {
676
681
  if (ts_key_eq(&acct->owner, params->program_id)) {
677
682
  SolPubkey derived;
678
683
  uint8_t bump;
679
684
  if (ts_find_pda(seeds, n, params->program_id, &derived, &bump) != SUCCESS ||
680
685
  !ts_key_eq(&derived, &acct->key))
681
686
  TS_FAIL(TS_ERR_SEEDS, "TypeSOL: PDA seeds do not match account");
682
- if (acct->data_len < space) TS_FAIL(TS_ERR_ACCOUNT_TOO_SMALL, "TypeSOL: account data too small");
687
+ if (acct->data_len < min_space) TS_FAIL(TS_ERR_ACCOUNT_TOO_SMALL, "TypeSOL: account data too small");
683
688
  if (!ts_mem_eq(acct->data, disc, 8)) TS_FAIL(TS_ERR_DISCRIMINATOR, "TypeSOL: account discriminator mismatch");
684
689
  *bump_out = bump;
685
690
  *created = false;
@@ -1209,9 +1214,21 @@ static inline uint64_t ts_metadata_address(const SolPubkey *mint, SolPubkey *out
1209
1214
  return SUCCESS;
1210
1215
  }
1211
1216
 
1217
+ static inline uint64_t ts_master_edition_address(const SolPubkey *mint, SolPubkey *out) {
1218
+ SolSignerSeed seeds[4] = {{(const uint8_t *)"metadata", 8},
1219
+ {(const uint8_t *)&TS_MPL_METADATA_ID, 32},
1220
+ {(const uint8_t *)mint, 32},
1221
+ {(const uint8_t *)"edition", 7}};
1222
+ uint8_t bump;
1223
+ if (ts_find_pda(seeds, 4, &TS_MPL_METADATA_ID, out, &bump) != SUCCESS)
1224
+ TS_FAIL(TS_ERR_SEEDS, "TypeSOL: cannot derive the master edition address");
1225
+ return SUCCESS;
1226
+ }
1227
+
1212
1228
  /*
1213
1229
  * Metaplex CreateMetadataAccountV3 (instruction 33): DataV2 { name, symbol, uri, seller_fee_basis_points u16,
1214
- * creators Option<Vec<Creator>>, collection Option<Collection>, uses None }, is_mutable bool, collection_details None.
1230
+ * creators Option<Vec<Creator>>, collection Option<Collection>, uses None }, is_mutable bool, collection_details
1231
+ * None, or Some(V1 { size: 0 }) when `sized_collection`.
1215
1232
  * `creators` holds `ncreators` packed Creator records (address, verified, share: 34 bytes); ncreators < 0 is None.
1216
1233
  * `collection` (NULL for None) is written unverified, as Metaplex requires at creation.
1217
1234
  * Accounts: metadata (w), mint, mint authority (s), payer (ws), update authority, system program.
@@ -1220,10 +1237,10 @@ static inline uint64_t ts_mpl_create_v3(TsParams *params, const TsAccount *progr
1220
1237
  TsAccount *mint, TsAccount *mint_authority, TsAccount *payer,
1221
1238
  TsAccount *update_authority, TsAccount *system, TS_Str name, TS_Str symbol,
1222
1239
  TS_Str uri, uint16_t fee_bps, bool is_mutable, const uint8_t *creators, int ncreators,
1223
- const SolPubkey *collection, const SolSignerSeed *seeds, int n) {
1240
+ const SolPubkey *collection, bool sized_collection, const SolSignerSeed *seeds, int n) {
1224
1241
  uint8_t *data;
1225
1242
  uint64_t ncr = ncreators > 0 ? (uint64_t)ncreators : 0;
1226
- TS_TRY(ts_alloc(1 + 12 + name.len + symbol.len + uri.len + 2 + (1 + 4 + 34 * ncr) + (1 + 33) + 1 + 1 + 1, &data));
1243
+ TS_TRY(ts_alloc(1 + 12 + name.len + symbol.len + uri.len + 2 + (1 + 4 + 34 * ncr) + (1 + 33) + 1 + 1 + (1 + 9), &data));
1227
1244
  uint64_t at = 0;
1228
1245
  data[at++] = 33;
1229
1246
  ts_put_str(data, &at, name);
@@ -1251,7 +1268,15 @@ static inline uint64_t ts_mpl_create_v3(TsParams *params, const TsAccount *progr
1251
1268
  }
1252
1269
  data[at++] = 0; /* uses: None */
1253
1270
  data[at++] = is_mutable ? 1 : 0;
1254
- data[at++] = 0; /* collection_details: None */
1271
+ if (sized_collection) {
1272
+ /* collection_details: Some(V1 { size: 0 }): this NFT is a collection items can be verified into */
1273
+ data[at++] = 1;
1274
+ data[at++] = 0;
1275
+ ts_memzero(data + at, 8);
1276
+ at += 8;
1277
+ } else {
1278
+ data[at++] = 0; /* collection_details: None */
1279
+ }
1255
1280
  bool ua_signs = update_authority->is_signer || ts_key_eq(&update_authority->key, &mint_authority->key);
1256
1281
  SolAccountMeta metas[6] = {{&metadata->key, true, false}, {&mint->key, false, false},
1257
1282
  {&mint_authority->key, false, true}, {&payer->key, true, true},