diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 78baeefa..c7c66003 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,6 +10,7 @@ env: SBPF_PROGRAM_PACKAGES: "['program', 'pinocchio-program']" RUST_PACKAGES: "['interface', 'program', 'mollusk_harness', 'pinocchio-interface', 'pinocchio-program']" WASM_PACKAGES: "['interface', 'program']" + IDL_PACKAGES: "['pinocchio-interface']" MIRI_PACKAGES: "['pinocchio-program']" jobs: @@ -20,6 +21,7 @@ jobs: SBPF_PROGRAM_PACKAGES: ${{ steps.compute.outputs.SBPF_PROGRAM_PACKAGES }} RUST_PACKAGES: ${{ steps.compute.outputs.RUST_PACKAGES }} WASM_PACKAGES: ${{ steps.compute.outputs.WASM_PACKAGES }} + IDL_PACKAGES: ${{ steps.compute.outputs.IDL_PACKAGES }} MIRI_PACKAGES: ${{ steps.compute.outputs.MIRI_PACKAGES }} RUST_TOOLCHAIN_NIGHTLY: ${{ steps.compute.outputs.RUST_TOOLCHAIN_NIGHTLY }} SOLANA_CLI_VERSION: ${{ steps.compute.outputs.SOLANA_CLI_VERSION }} @@ -34,6 +36,7 @@ jobs: echo "SBPF_PROGRAM_PACKAGES=${{ env.SBPF_PROGRAM_PACKAGES }}" >> $GITHUB_OUTPUT echo "RUST_PACKAGES=${{ env.RUST_PACKAGES }}" >> $GITHUB_OUTPUT echo "WASM_PACKAGES=${{ env.WASM_PACKAGES }}" >> $GITHUB_OUTPUT + echo "IDL_PACKAGES=${{ env.IDL_PACKAGES }}" >> $GITHUB_OUTPUT echo "MIRI_PACKAGES=${{ env.MIRI_PACKAGES }}" >> $GITHUB_OUTPUT echo "RUST_TOOLCHAIN_NIGHTLY=$(make rust-toolchain-nightly)" >> "$GITHUB_OUTPUT" echo "SOLANA_CLI_VERSION=$(make solana-cli-version)" >> "$GITHUB_OUTPUT" @@ -45,6 +48,7 @@ jobs: sbpf-program-packages: ${{ needs.set_env.outputs.SBPF_PROGRAM_PACKAGES }} rust-packages: ${{ needs.set_env.outputs.RUST_PACKAGES }} wasm-packages: ${{ needs.set_env.outputs.WASM_PACKAGES }} + idl-packages: ${{ needs.set_env.outputs.IDL_PACKAGES }} rustfmt-toolchain: ${{ needs.set_env.outputs.RUST_TOOLCHAIN_NIGHTLY }} clippy-toolchain: ${{ needs.set_env.outputs.RUST_TOOLCHAIN_NIGHTLY }} solana-cli-version: ${{ needs.set_env.outputs.SOLANA_CLI_VERSION }} diff --git a/Cargo.lock b/Cargo.lock index f979ab0c..2ce6b9cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -583,6 +583,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cargo_toml" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88da5a13c620b4ca0078845707ea9c3faf11edbc3ffd8497d11d686211cd1ac0" +dependencies = [ + "serde", + "toml", +] + [[package]] name = "cc" version = "1.2.56" @@ -615,6 +625,160 @@ dependencies = [ "inout", ] +[[package]] +name = "codama" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf2f908673e3177aa1c6546b61fac36874efba6754ffa2b6082f676bd8fa3e0" +dependencies = [ + "codama-errors", + "codama-korok-plugins", + "codama-korok-visitors", + "codama-koroks", + "codama-macros", + "codama-nodes", + "codama-stores", + "proc-macro2", +] + +[[package]] +name = "codama-attributes" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce088c3f23ad6a6f9b69da81751c87212da2c2195f1b3e391619c3b626473c25" +dependencies = [ + "codama-errors", + "codama-nodes", + "codama-syn-helpers", + "derive_more", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "codama-errors" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485d98de3a1cfd25975cc5afca9c8e03da3ae85c0e4ef1ad818579f7fdc640a" +dependencies = [ + "cargo_toml", + "proc-macro2", + "serde_json", + "syn 2.0.117", + "thiserror 2.0.18", +] + +[[package]] +name = "codama-korok-plugins" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c0899cf03caae88577f4423bebb84659778fca4db1caf4f9dd777ac16f8406" +dependencies = [ + "codama-errors", + "codama-korok-visitors", + "codama-koroks", +] + +[[package]] +name = "codama-korok-visitors" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b3b1d119c0b247a4746f963bb05e7470d7a3729da8f4040144eea4745e73ac1" +dependencies = [ + "cargo_toml", + "codama-attributes", + "codama-errors", + "codama-koroks", + "codama-nodes", + "codama-syn-helpers", + "serde_json", + "syn 2.0.117", +] + +[[package]] +name = "codama-koroks" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fb43f91eef59c2e4ca8b7c9f54026a5f43f6f3b3c0505ed77be1abd900525ce" +dependencies = [ + "codama-attributes", + "codama-errors", + "codama-nodes", + "codama-stores", + "codama-syn-helpers", + "derive_more", + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "codama-macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f20101421d0bc92133bdfb99be7585196e6313c8665bbdb5830701ab7ca85ee" +dependencies = [ + "codama-attributes", + "codama-errors", + "codama-koroks", + "codama-stores", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "codama-nodes" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b4a10746031fb835ee90b0f1d67844de91e938d93df6167129325bb886a5da" +dependencies = [ + "codama-errors", + "codama-nodes-derive", + "derive_more", + "serde", + "serde_json", +] + +[[package]] +name = "codama-nodes-derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e195f4c7b6a93180a3eb59ba53016d4ea4bbef212f78fa6a04835fe244cb3da1" +dependencies = [ + "codama-errors", + "codama-syn-helpers", + "derive_more", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "codama-stores" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56bd0a298e94a566dbd3451d1613ba1f7290bfbaa38e66b8ebd0d3688824bd59" +dependencies = [ + "cargo_toml", + "codama-errors", + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "codama-syn-helpers" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dd908283642bba89c720b5f58d43746e7a3506a960b90357ce64e160381374" +dependencies = [ + "codama-errors", + "derive_more", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "colorchoice" version = "1.0.4" @@ -784,6 +948,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "digest" version = "0.9.0" @@ -1651,6 +1835,8 @@ dependencies = [ name = "pinocchio-associated-token-account-interface" version = "0.1.0" dependencies = [ + "codama", + "codama-macros", "solana-address 2.2.0", ] @@ -1714,7 +1900,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit", + "toml_edit 0.23.10+spec-1.0.0", ] [[package]] @@ -2009,6 +2195,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "sha2" version = "0.9.9" @@ -3515,6 +3710,27 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" @@ -3524,6 +3740,20 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_write", + "winnow", +] + [[package]] name = "toml_edit" version = "0.23.10+spec-1.0.0" @@ -3531,7 +3761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", ] @@ -3545,6 +3775,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "typenum" version = "1.19.0" diff --git a/Makefile b/Makefile index 03eeb3f1..39f403a9 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,10 @@ cargo-nightly: generate-clients: @echo "No JavaScript clients to generate" +generate-idl-%: + @cargo install --locked --version =0.7.3 codama-cli + codama-rs generate-idl $(call make-path,$*) -o $(call make-path,$*)/idl.json --pretty $(ARGS) + audit: cargo audit \ --ignore RUSTSEC-2022-0093 \ diff --git a/README.md b/README.md index cabf1863..5be79ce5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # associated-token-account -The SPL Associated Token Account program and its clients +The SPL Associated Token Account program diff --git a/pinocchio/interface/Cargo.toml b/pinocchio/interface/Cargo.toml index 6e7635d4..fe7c5136 100644 --- a/pinocchio/interface/Cargo.toml +++ b/pinocchio/interface/Cargo.toml @@ -10,7 +10,12 @@ edition = "2021" [lib] crate-type = ["rlib"] +[features] +codama = ["dep:codama", "dep:codama-macros"] + [dependencies] +codama = { version = "0.7.3", optional = true } +codama-macros = { version = "0.7.3", optional = true } solana-address = { version = "2.2.0", features = ["decode"] } [package.metadata.solana] diff --git a/pinocchio/interface/README.md b/pinocchio/interface/README.md index 14b99569..5529c896 100644 --- a/pinocchio/interface/README.md +++ b/pinocchio/interface/README.md @@ -1,3 +1,19 @@ # `pinocchio-associated-token-account-interface` Pinocchio instructions and types for interacting with the Associated Token Account program. + +## Codama + +This crate includes Codama macros. + +Generate the IDL from repo root: + +```bash +make generate-idl-pinocchio-interface +``` + +This writes: + +```text +pinocchio/interface/idl.json +``` diff --git a/pinocchio/interface/idl.json b/pinocchio/interface/idl.json new file mode 100644 index 00000000..c51e9254 --- /dev/null +++ b/pinocchio/interface/idl.json @@ -0,0 +1,284 @@ +{ + "kind": "rootNode", + "standard": "codama", + "version": "1.0.0", + "program": { + "kind": "programNode", + "name": "pinocchioAssociatedTokenAccountInterface", + "publicKey": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "version": "0.1.0", + "accounts": [], + "instructions": [ + { + "kind": "instructionNode", + "name": "create", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "funder", + "isWritable": true, + "isSigner": true, + "docs": [ + "Funding account (must be a system account)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "associatedTokenAccount", + "isWritable": true, + "isSigner": false, + "docs": [ + "Associated token account address to be created" + ] + }, + { + "kind": "instructionAccountNode", + "name": "wallet", + "isWritable": false, + "isSigner": false, + "docs": [ + "Wallet address for the new associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": false, + "isSigner": false, + "docs": [ + "The token mint for the new associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "docs": [ + "System program" + ], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111" + } + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "docs": [ + "SPL Token program" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 0 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createIdempotent", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "funder", + "isWritable": true, + "isSigner": true, + "docs": [ + "Funding account (must be a system account)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "associatedTokenAccount", + "isWritable": true, + "isSigner": false, + "docs": [ + "Associated token account address to be created" + ] + }, + { + "kind": "instructionAccountNode", + "name": "wallet", + "isWritable": false, + "isSigner": false, + "docs": [ + "Wallet address for the new associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": false, + "isSigner": false, + "docs": [ + "The token mint for the new associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "docs": [ + "System program" + ], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111" + } + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "docs": [ + "SPL Token program" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 1 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "recoverNested", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "nestedAssociatedTokenAccount", + "isWritable": true, + "isSigner": false, + "docs": [ + "Nested associated token account, must be owned by `owner_associated_token_account`" + ] + }, + { + "kind": "instructionAccountNode", + "name": "nestedMint", + "isWritable": false, + "isSigner": false, + "docs": [ + "Token mint for the nested associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "destinationAssociatedTokenAccount", + "isWritable": true, + "isSigner": false, + "docs": [ + "Wallet's associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "ownerAssociatedTokenAccount", + "isWritable": false, + "isSigner": false, + "docs": [ + "Owner associated token account address, must be owned by `wallet`" + ] + }, + { + "kind": "instructionAccountNode", + "name": "ownerMint", + "isWritable": false, + "isSigner": false, + "docs": [ + "Token mint for the owner associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "wallet", + "isWritable": true, + "isSigner": true, + "docs": [ + "Wallet address for the owner associated token account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "docs": [ + "SPL Token program" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 2 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + } + ], + "definedTypes": [], + "pdas": [], + "errors": [] + }, + "additionalPrograms": [] +} \ No newline at end of file diff --git a/pinocchio/interface/src/instruction.rs b/pinocchio/interface/src/instruction.rs index df009aad..fe8cfa33 100644 --- a/pinocchio/interface/src/instruction.rs +++ b/pinocchio/interface/src/instruction.rs @@ -1,8 +1,12 @@ //! Instruction types for the Associated Token Account program. +#[cfg(feature = "codama")] +use codama_macros::CodamaInstructions; + /// Instructions supported by the `AssociatedTokenAccount` program #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "codama", derive(CodamaInstructions))] pub enum AssociatedTokenAccountInstruction { /// Creates an associated token account for the given wallet address and /// token mint Returns an error if the account exists. @@ -13,6 +17,28 @@ pub enum AssociatedTokenAccountInstruction { /// 3. `[]` The token mint for the new associated token account /// 4. `[]` System program /// 5. `[]` SPL Token program + #[cfg_attr( + feature = "codama", + codama(account( + name = "funder", + signer, + writable, + docs = "Funding account (must be a system account)" + )), + codama(account( + name = "associated_token_account", + writable, + docs = "Associated token account address to be created" + )), + codama(account(name = "wallet", docs = "Wallet address for the new associated token account")), + codama(account(name = "mint", docs = "The token mint for the new associated token account")), + codama(account( + name = "system_program", + docs = "System program", + default_value = program("system") + )), + codama(account(name = "token_program", docs = "SPL Token program")) + )] Create, /// Creates an associated token account for the given wallet address and /// token mint, if it doesn't already exist. Returns an error if the @@ -24,6 +50,28 @@ pub enum AssociatedTokenAccountInstruction { /// 3. `[]` The token mint for the new associated token account /// 4. `[]` System program /// 5. `[]` SPL Token program + #[cfg_attr( + feature = "codama", + codama(account( + name = "funder", + signer, + writable, + docs = "Funding account (must be a system account)" + )), + codama(account( + name = "associated_token_account", + writable, + docs = "Associated token account address to be created" + )), + codama(account(name = "wallet", docs = "Wallet address for the new associated token account")), + codama(account(name = "mint", docs = "The token mint for the new associated token account")), + codama(account( + name = "system_program", + docs = "System program", + default_value = program("system") + )), + codama(account(name = "token_program", docs = "SPL Token program")) + )] CreateIdempotent, /// Transfers from and closes a nested associated token account: an /// associated token account owned by an associated token account. @@ -44,6 +92,38 @@ pub enum AssociatedTokenAccountInstruction { /// 5. `[writeable, signer]` Wallet address for the owner associated token /// account /// 6. `[]` SPL Token program + #[cfg_attr( + feature = "codama", + codama(account( + name = "nested_associated_token_account", + writable, + docs = "Nested associated token account, must be owned by `owner_associated_token_account`" + )), + codama(account( + name = "nested_mint", + docs = "Token mint for the nested associated token account" + )), + codama(account( + name = "destination_associated_token_account", + writable, + docs = "Wallet's associated token account" + )), + codama(account( + name = "owner_associated_token_account", + docs = "Owner associated token account address, must be owned by `wallet`" + )), + codama(account( + name = "owner_mint", + docs = "Token mint for the owner associated token account" + )), + codama(account( + name = "wallet", + signer, + writable, + docs = "Wallet address for the owner associated token account" + )), + codama(account(name = "token_program", docs = "SPL Token program")) + )] RecoverNested, } diff --git a/scripts/solana.dic b/scripts/solana.dic index fa7b2474..57e2efb5 100644 --- a/scripts/solana.dic +++ b/scripts/solana.dic @@ -52,3 +52,4 @@ autogenerated ATA pinocchio Pinocchio +IDL